feat: expose instruction types and refactor

This commit is contained in:
Justin Starry 2020-02-28 18:43:10 +08:00 committed by Michael Vines
parent 8b95f41c51
commit 0cdf532419
7 changed files with 305 additions and 165 deletions

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

@ -233,73 +233,6 @@ declare module '@solana/web3.js' {
): Promise<number>; ): Promise<number>;
} }
// === src/stake-program.js ===
export type StakeAuthorizationType = {
index: number;
};
export class Authorized {
staker: PublicKey;
withdrawer: PublicKey;
constructor(staker: PublicKey, withdrawer: PublicKey);
}
export class Lockup {
unixTimestamp: number;
epoch: number;
custodian: PublicKey;
constructor(unixTimestamp: number, epoch: number, custodian: PublicKey);
}
export class StakeProgram {
static programId: PublicKey;
static space: number;
static createAccount(
from: PublicKey,
stakeAccount: PublicKey,
authorized: Authorized,
lockup: Lockup,
lamports: number,
): Transaction;
static createAccountWithSeed(
from: PublicKey,
stakeAccount: PublicKey,
seed: string,
authorized: Authorized,
lockup: Lockup,
lamports: number,
): Transaction;
static delegate(
stakeAccount: PublicKey,
authorizedPubkey: PublicKey,
votePubkey: PublicKey,
): Transaction;
static authorize(
stakeAccount: PublicKey,
authorizedPubkey: PublicKey,
newAuthorized: PublicKey,
stakeAuthorizationType: StakeAuthorizationType,
): Transaction;
static split(
stakeAccount: PublicKey,
authorizedPubkey: PublicKey,
lamports: number,
splitStakePubkey: PublicKey,
): Transaction;
static withdraw(
stakeAccount: PublicKey,
withdrawerPubkey: PublicKey,
to: PublicKey,
lamports: number,
): Transaction;
static deactivate(
stakeAccount: PublicKey,
authorizedPubkey: PublicKey,
): Transaction;
}
// === src/validator-info.js === // === src/validator-info.js ===
export const VALIDATOR_INFO_KEY: PublicKey; export const VALIDATOR_INFO_KEY: PublicKey;
export type Info = { export type Info = {
@ -421,6 +354,97 @@ declare module '@solana/web3.js' {
serialize(): Buffer; serialize(): Buffer;
} }
// === src/stake-program.js ===
export type StakeAuthorizationType = {
index: number;
};
export class Authorized {
staker: PublicKey;
withdrawer: PublicKey;
constructor(staker: PublicKey, withdrawer: PublicKey);
}
export class Lockup {
unixTimestamp: number;
epoch: number;
custodian: PublicKey;
constructor(unixTimestamp: number, epoch: number, custodian: PublicKey);
}
export class StakeProgram {
static programId: PublicKey;
static space: number;
static createAccount(
from: PublicKey,
stakeAccount: PublicKey,
authorized: Authorized,
lockup: Lockup,
lamports: number,
): Transaction;
static createAccountWithSeed(
from: PublicKey,
stakeAccount: PublicKey,
seed: string,
authorized: Authorized,
lockup: Lockup,
lamports: number,
): Transaction;
static delegate(
stakeAccount: PublicKey,
authorizedPubkey: PublicKey,
votePubkey: PublicKey,
): Transaction;
static authorize(
stakeAccount: PublicKey,
authorizedPubkey: PublicKey,
newAuthorized: PublicKey,
stakeAuthorizationType: StakeAuthorizationType,
): Transaction;
static split(
stakeAccount: PublicKey,
authorizedPubkey: PublicKey,
lamports: number,
splitStakePubkey: PublicKey,
): Transaction;
static withdraw(
stakeAccount: PublicKey,
withdrawerPubkey: PublicKey,
to: PublicKey,
lamports: number,
): Transaction;
static deactivate(
stakeAccount: PublicKey,
authorizedPubkey: PublicKey,
): Transaction;
}
export type StakeInstructionType =
| 'Initialize'
| 'Authorize'
| 'Delegate'
| 'Split'
| 'Withdraw'
| 'Deactivate';
export const STAKE_INSTRUCTION_LAYOUTS: {
[StakeInstructionType]: InstructionType;
};
export class StakeInstruction extends TransactionInstruction {
type: StakeInstructionType;
stakePublicKey: PublicKey | null;
authorizedPublicKey: PublicKey | null;
constructor(
opts?: TransactionInstructionCtorFields,
type: StakeInstructionType,
);
static from(instruction: TransactionInstruction): StakeInstruction;
}
// === src/system-program.js === // === src/system-program.js ===
export class SystemProgram { export class SystemProgram {
static programId: PublicKey; static programId: PublicKey;
@ -471,15 +495,29 @@ declare module '@solana/web3.js' {
): Transaction; ): Transaction;
} }
export type SystemInstructionType =
| 'Create'
| 'Assign'
| 'Transfer'
| 'CreateWithSeed'
| 'AdvanceNonceAccount'
| 'WithdrawNonceAccount'
| 'InitializeNonceAccount'
| 'AuthorizeNonceAccount';
export const SYSTEM_INSTRUCTION_LAYOUTS: {
[SystemInstructionType]: InstructionType;
};
export class SystemInstruction extends TransactionInstruction { export class SystemInstruction extends TransactionInstruction {
type: InstructionType; type: SystemInstructionType;
fromPublicKey: PublicKey | null; fromPublicKey: PublicKey | null;
toPublicKey: PublicKey | null; toPublicKey: PublicKey | null;
amount: number | null; amount: number | null;
constructor( constructor(
opts?: TransactionInstructionCtorFields, opts?: TransactionInstructionCtorFields,
type?: InstructionType, type: SystemInstructionType,
); );
static from(instruction: TransactionInstruction): SystemInstruction; static from(instruction: TransactionInstruction): SystemInstruction;
} }

View File

@ -318,6 +318,30 @@ declare module '@solana/web3.js' {
): Transaction; ): Transaction;
} }
declare export type StakeInstructionType =
| 'Initialize'
| 'Authorize'
| 'Delegate'
| 'Split'
| 'Withdraw'
| 'Deactivate';
declare export var STAKE_INSTRUCTION_LAYOUTS: {
[StakeInstructionType]: InstructionType,
};
declare export class StakeInstruction extends TransactionInstruction {
type: StakeInstructionType;
stakePublicKey: PublicKey | null;
authorizedPublicKey: PublicKey | null;
constructor(
opts?: TransactionInstructionCtorFields,
type: StakeInstructionType,
): StakeInstruction;
static from(instruction: TransactionInstruction): StakeInstruction;
}
// === src/system-program.js === // === src/system-program.js ===
declare export class SystemProgram { declare export class SystemProgram {
static programId: PublicKey; static programId: PublicKey;
@ -368,15 +392,29 @@ declare module '@solana/web3.js' {
): Transaction; ): Transaction;
} }
declare export type SystemInstructionType =
| 'Create'
| 'Assign'
| 'Transfer'
| 'CreateWithSeed'
| 'AdvanceNonceAccount'
| 'WithdrawNonceAccount'
| 'InitializeNonceAccount'
| 'AuthorizeNonceAccount';
declare export var SYSTEM_INSTRUCTION_LAYOUTS: {
[SystemInstructionType]: InstructionType,
};
declare export class SystemInstruction extends TransactionInstruction { declare export class SystemInstruction extends TransactionInstruction {
type: InstructionType; type: SystemInstructionType;
fromPublicKey: PublicKey | null; fromPublicKey: PublicKey | null;
toPublicKey: PublicKey | null; toPublicKey: PublicKey | null;
amount: number | null; amount: number | null;
constructor( constructor(
opts?: TransactionInstructionCtorFields, opts?: TransactionInstructionCtorFields,
type?: InstructionType, type: SystemInstructionType,
): SystemInstruction; ): SystemInstruction;
static from(instruction: TransactionInstruction): SystemInstruction; static from(instruction: TransactionInstruction): SystemInstruction;
} }

View File

@ -12,7 +12,7 @@ export {
Lockup, Lockup,
StakeAuthorizationLayout, StakeAuthorizationLayout,
StakeInstruction, StakeInstruction,
StakeInstructionLayout, STAKE_INSTRUCTION_LAYOUTS,
StakeProgram, StakeProgram,
} from './stake-program'; } from './stake-program';
export {SystemInstruction, SystemProgram} from './system-program'; export {SystemInstruction, SystemProgram} from './system-program';

View File

@ -3,7 +3,6 @@
import * as BufferLayout from 'buffer-layout'; import * as BufferLayout from 'buffer-layout';
import {encodeData} from './instruction'; import {encodeData} from './instruction';
import type {InstructionType} from './instruction';
import * as Layout from './layout'; import * as Layout from './layout';
import {PublicKey} from './publickey'; import {PublicKey} from './publickey';
import {SystemProgram} from './system-program'; import {SystemProgram} from './system-program';
@ -51,12 +50,12 @@ export class Lockup {
* Stake Instruction class * Stake Instruction class
*/ */
export class StakeInstruction extends TransactionInstruction { export class StakeInstruction extends TransactionInstruction {
/** _type: StakeInstructionType;
* Type of StakeInstruction
*/
type: InstructionType;
constructor(opts?: TransactionInstructionCtorFields, type?: InstructionType) { constructor(
opts?: TransactionInstructionCtorFields,
type: StakeInstructionType,
) {
if ( if (
opts && opts &&
opts.programId && opts.programId &&
@ -65,9 +64,7 @@ export class StakeInstruction extends TransactionInstruction {
throw new Error('programId incorrect; not a StakeInstruction'); throw new Error('programId incorrect; not a StakeInstruction');
} }
super(opts); super(opts);
if (type) { this._type = type;
this.type = type;
}
} }
static from(instruction: TransactionInstruction): StakeInstruction { static from(instruction: TransactionInstruction): StakeInstruction {
@ -77,10 +74,11 @@ export class StakeInstruction extends TransactionInstruction {
const instructionTypeLayout = BufferLayout.u32('instruction'); const instructionTypeLayout = BufferLayout.u32('instruction');
const typeIndex = instructionTypeLayout.decode(instruction.data); const typeIndex = instructionTypeLayout.decode(instruction.data);
let type; let type;
for (const t in StakeInstructionLayout) { for (const t of Object.keys(STAKE_INSTRUCTION_LAYOUTS)) {
if (StakeInstructionLayout[t].index == typeIndex) { if (STAKE_INSTRUCTION_LAYOUTS[t].index == typeIndex) {
type = StakeInstructionLayout[t]; type = t;
} }
} }
if (!type) { if (!type) {
@ -95,12 +93,66 @@ export class StakeInstruction extends TransactionInstruction {
type, type,
); );
} }
/**
* Type of StakeInstruction
*/
get type(): StakeInstructionType {
return this._type;
}
/**
* The `stake account` public key of the instruction;
* returns null if StakeInstructionType does not support this field
*/
get stakePublicKey(): PublicKey | null {
switch (this.type) {
case STAKE_INSTRUCTION_LAYOUTS.Initialize:
case STAKE_INSTRUCTION_LAYOUTS.Delegate:
case STAKE_INSTRUCTION_LAYOUTS.Authorize:
case STAKE_INSTRUCTION_LAYOUTS.Split:
case STAKE_INSTRUCTION_LAYOUTS.Withdraw:
case STAKE_INSTRUCTION_LAYOUTS.Deactivate:
return this.keys[0].pubkey;
default:
return null;
}
}
/**
* The `authorized account` public key of the instruction;
*
* returns null if StakeInstructionType does not support this field
*/
get authorizedPublicKey(): PublicKey | null {
switch (this.type) {
case STAKE_INSTRUCTION_LAYOUTS.Delegate:
return this.keys[5].pubkey;
case STAKE_INSTRUCTION_LAYOUTS.Authorize:
return this.keys[2].pubkey;
case STAKE_INSTRUCTION_LAYOUTS.Split:
return this.keys[2].pubkey;
case STAKE_INSTRUCTION_LAYOUTS.Withdraw:
return this.keys[4].pubkey;
case STAKE_INSTRUCTION_LAYOUTS.Deactivate:
return this.keys[0].pubkey;
default:
return null;
}
}
} }
/** /**
* An enumeration of valid StakeInstructionTypes * An enumeration of valid StakeInstructionType's
* @typedef { 'Initialize' | 'Authorize' | 'Delegate' | 'Split' | 'Withdraw'
| 'Deactivate' } StakeInstructionType
*/ */
export const StakeInstructionLayout = Object.freeze({ export type StakeInstructionType = $Keys<typeof STAKE_INSTRUCTION_LAYOUTS>;
/**
* An enumeration of valid stake InstructionType's
*/
export const STAKE_INSTRUCTION_LAYOUTS = Object.freeze({
Initialize: { Initialize: {
index: 0, index: 0,
layout: BufferLayout.struct([ layout: BufferLayout.struct([
@ -117,7 +169,7 @@ export const StakeInstructionLayout = Object.freeze({
BufferLayout.u32('stakeAuthorizationType'), BufferLayout.u32('stakeAuthorizationType'),
]), ]),
}, },
DelegateStake: { Delegate: {
index: 2, index: 2,
layout: BufferLayout.struct([BufferLayout.u32('instruction')]), layout: BufferLayout.struct([BufferLayout.u32('instruction')]),
}, },
@ -150,7 +202,7 @@ export type StakeAuthorizationType = {|
|}; |};
/** /**
* An enumeration of valid StakeInstructionTypes * An enumeration of valid StakeAuthorizationLayout's
*/ */
export const StakeAuthorizationLayout = Object.freeze({ export const StakeAuthorizationLayout = Object.freeze({
Staker: { Staker: {
@ -183,11 +235,11 @@ export class StakeProgram {
* Generate an Initialize instruction to add to a Stake Create transaction * Generate an Initialize instruction to add to a Stake Create transaction
*/ */
static initialize( static initialize(
stakeAccount: PublicKey, stakePubkey: PublicKey,
authorized: Authorized, authorized: Authorized,
lockup: Lockup, lockup: Lockup,
): TransactionInstruction { ): TransactionInstruction {
const type = StakeInstructionLayout.Initialize; const type = STAKE_INSTRUCTION_LAYOUTS.Initialize;
const data = encodeData(type, { const data = encodeData(type, {
authorized: { authorized: {
staker: authorized.staker.toBuffer(), staker: authorized.staker.toBuffer(),
@ -201,7 +253,7 @@ export class StakeProgram {
}); });
const instructionData = { const instructionData = {
keys: [ keys: [
{pubkey: stakeAccount, isSigner: false, isWritable: true}, {pubkey: stakePubkey, isSigner: false, isWritable: true},
{pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false}, {pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false},
], ],
programId: this.programId, programId: this.programId,
@ -216,7 +268,7 @@ export class StakeProgram {
*/ */
static createAccountWithSeed( static createAccountWithSeed(
from: PublicKey, from: PublicKey,
stakeAccount: PublicKey, stakePubkey: PublicKey,
base: PublicKey, base: PublicKey,
seed: string, seed: string,
authorized: Authorized, authorized: Authorized,
@ -225,7 +277,7 @@ export class StakeProgram {
): Transaction { ): Transaction {
let transaction = SystemProgram.createAccountWithSeed( let transaction = SystemProgram.createAccountWithSeed(
from, from,
stakeAccount, stakePubkey,
base, base,
seed, seed,
lamports, lamports,
@ -233,7 +285,7 @@ export class StakeProgram {
this.programId, this.programId,
); );
return transaction.add(this.initialize(stakeAccount, authorized, lockup)); return transaction.add(this.initialize(stakePubkey, authorized, lockup));
} }
/** /**
@ -241,20 +293,20 @@ export class StakeProgram {
*/ */
static createAccount( static createAccount(
from: PublicKey, from: PublicKey,
stakeAccount: PublicKey, stakePubkey: PublicKey,
authorized: Authorized, authorized: Authorized,
lockup: Lockup, lockup: Lockup,
lamports: number, lamports: number,
): Transaction { ): Transaction {
let transaction = SystemProgram.createAccount( let transaction = SystemProgram.createAccount(
from, from,
stakeAccount, stakePubkey,
lamports, lamports,
this.space, this.space,
this.programId, this.programId,
); );
return transaction.add(this.initialize(stakeAccount, authorized, lockup)); return transaction.add(this.initialize(stakePubkey, authorized, lockup));
} }
/** /**
@ -263,16 +315,16 @@ export class StakeProgram {
* to a new validator Vote PublicKey. * to a new validator Vote PublicKey.
*/ */
static delegate( static delegate(
stakeAccount: PublicKey, stakePubkey: PublicKey,
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
votePubkey: PublicKey, votePubkey: PublicKey,
): Transaction { ): Transaction {
const type = StakeInstructionLayout.DelegateStake; const type = STAKE_INSTRUCTION_LAYOUTS.Delegate;
const data = encodeData(type); const data = encodeData(type);
return new Transaction().add({ return new Transaction().add({
keys: [ keys: [
{pubkey: stakeAccount, isSigner: false, isWritable: true}, {pubkey: stakePubkey, isSigner: false, isWritable: true},
{pubkey: votePubkey, isSigner: false, isWritable: false}, {pubkey: votePubkey, isSigner: false, isWritable: false},
{pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false}, {pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false},
{ {
@ -293,12 +345,12 @@ export class StakeProgram {
* or Withdrawer on the Stake account. * or Withdrawer on the Stake account.
*/ */
static authorize( static authorize(
stakeAccount: PublicKey, stakePubkey: PublicKey,
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
newAuthorized: PublicKey, newAuthorized: PublicKey,
stakeAuthorizationType: StakeAuthorizationType, stakeAuthorizationType: StakeAuthorizationType,
): Transaction { ): Transaction {
const type = StakeInstructionLayout.Authorize; const type = STAKE_INSTRUCTION_LAYOUTS.Authorize;
const data = encodeData(type, { const data = encodeData(type, {
newAuthorized: newAuthorized.toBuffer(), newAuthorized: newAuthorized.toBuffer(),
stakeAuthorizationType: stakeAuthorizationType.index, stakeAuthorizationType: stakeAuthorizationType.index,
@ -306,7 +358,7 @@ export class StakeProgram {
return new Transaction().add({ return new Transaction().add({
keys: [ keys: [
{pubkey: stakeAccount, 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},
], ],
@ -319,25 +371,25 @@ export class StakeProgram {
* Generate a Transaction that splits Stake tokens into another stake account * Generate a Transaction that splits Stake tokens into another stake account
*/ */
static split( static split(
stakeAccount: PublicKey, stakePubkey: PublicKey,
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
lamports: number, lamports: number,
splitStakePubkey: PublicKey, splitStakePubkey: PublicKey,
): Transaction { ): Transaction {
let transaction = SystemProgram.createAccount( let transaction = SystemProgram.createAccount(
stakeAccount, stakePubkey,
splitStakePubkey, splitStakePubkey,
0, 0,
this.space, this.space,
this.programId, this.programId,
); );
transaction.instructions[0].keys[0].isSigner = false; transaction.instructions[0].keys[0].isSigner = false;
const type = StakeInstructionLayout.Split; const type = STAKE_INSTRUCTION_LAYOUTS.Split;
const data = encodeData(type, {lamports}); const data = encodeData(type, {lamports});
return transaction.add({ return transaction.add({
keys: [ keys: [
{pubkey: stakeAccount, isSigner: false, isWritable: true}, {pubkey: stakePubkey, isSigner: false, isWritable: true},
{pubkey: splitStakePubkey, isSigner: false, isWritable: true}, {pubkey: splitStakePubkey, isSigner: false, isWritable: true},
{pubkey: authorizedPubkey, isSigner: true, isWritable: false}, {pubkey: authorizedPubkey, isSigner: true, isWritable: false},
], ],
@ -350,17 +402,17 @@ export class StakeProgram {
* Generate a Transaction that withdraws deactivated Stake tokens. * Generate a Transaction that withdraws deactivated Stake tokens.
*/ */
static withdraw( static withdraw(
stakeAccount: PublicKey, stakePubkey: PublicKey,
withdrawerPubkey: PublicKey, authorizedPubkey: PublicKey,
to: PublicKey, to: PublicKey,
lamports: number, lamports: number,
): Transaction { ): Transaction {
const type = StakeInstructionLayout.Withdraw; const type = STAKE_INSTRUCTION_LAYOUTS.Withdraw;
const data = encodeData(type, {lamports}); const data = encodeData(type, {lamports});
return new Transaction().add({ return new Transaction().add({
keys: [ keys: [
{pubkey: stakeAccount, isSigner: false, isWritable: true}, {pubkey: stakePubkey, isSigner: false, isWritable: true},
{pubkey: to, isSigner: false, isWritable: true}, {pubkey: to, isSigner: false, isWritable: true},
{pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false}, {pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false},
{ {
@ -368,7 +420,7 @@ export class StakeProgram {
isSigner: false, isSigner: false,
isWritable: false, isWritable: false,
}, },
{pubkey: withdrawerPubkey, isSigner: true, isWritable: false}, {pubkey: authorizedPubkey, isSigner: true, isWritable: false},
], ],
programId: this.programId, programId: this.programId,
data, data,
@ -379,15 +431,15 @@ export class StakeProgram {
* Generate a Transaction that deactivates Stake tokens. * Generate a Transaction that deactivates Stake tokens.
*/ */
static deactivate( static deactivate(
stakeAccount: PublicKey, stakePubkey: PublicKey,
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
): Transaction { ): Transaction {
const type = StakeInstructionLayout.Deactivate; const type = STAKE_INSTRUCTION_LAYOUTS.Deactivate;
const data = encodeData(type); const data = encodeData(type);
return new Transaction().add({ return new Transaction().add({
keys: [ keys: [
{pubkey: stakeAccount, isSigner: false, isWritable: true}, {pubkey: stakePubkey, isSigner: false, isWritable: true},
{pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false}, {pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false},
{pubkey: authorizedPubkey, isSigner: true, isWritable: false}, {pubkey: authorizedPubkey, isSigner: true, isWritable: false},
], ],

View File

@ -3,7 +3,6 @@
import * as BufferLayout from 'buffer-layout'; import * as BufferLayout from 'buffer-layout';
import {encodeData} from './instruction'; import {encodeData} from './instruction';
import type {InstructionType} from './instruction';
import * as Layout from './layout'; import * as Layout from './layout';
import {PublicKey} from './publickey'; import {PublicKey} from './publickey';
import {SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY} from './sysvar'; import {SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY} from './sysvar';
@ -17,9 +16,12 @@ export class SystemInstruction extends TransactionInstruction {
/** /**
* Type of SystemInstruction * Type of SystemInstruction
*/ */
type: InstructionType; _type: SystemInstructionType;
constructor(opts?: TransactionInstructionCtorFields, type?: InstructionType) { constructor(
opts?: TransactionInstructionCtorFields,
type: SystemInstructionType,
) {
if ( if (
opts && opts &&
opts.programId && opts.programId &&
@ -28,9 +30,7 @@ export class SystemInstruction extends TransactionInstruction {
throw new Error('programId incorrect; not a SystemInstruction'); throw new Error('programId incorrect; not a SystemInstruction');
} }
super(opts); super(opts);
if (type) { this._type = type;
this.type = type;
}
} }
static from(instruction: TransactionInstruction): SystemInstruction { static from(instruction: TransactionInstruction): SystemInstruction {
@ -41,9 +41,9 @@ export class SystemInstruction extends TransactionInstruction {
const instructionTypeLayout = BufferLayout.u32('instruction'); const instructionTypeLayout = BufferLayout.u32('instruction');
const typeIndex = instructionTypeLayout.decode(instruction.data); const typeIndex = instructionTypeLayout.decode(instruction.data);
let type; let type;
for (const t in SystemInstructionLayout) { for (const t of Object.keys(SYSTEM_INSTRUCTION_LAYOUTS)) {
if (SystemInstructionLayout[t].index == typeIndex) { if (SYSTEM_INSTRUCTION_LAYOUTS[t].index == typeIndex) {
type = SystemInstructionLayout[t]; type = t;
} }
} }
if (!type) { if (!type) {
@ -59,60 +59,75 @@ export class SystemInstruction extends TransactionInstruction {
); );
} }
/**
* Type of SystemInstruction
*/
get type(): SystemInstructionType {
return this._type;
}
/** /**
* The `from` public key of the instruction; * The `from` public key of the instruction;
* returns null if SystemInstructionType does not support this field * returns null if SystemInstructionType does not support this field
*/ */
get fromPublicKey(): PublicKey | null { get fromPublicKey(): PublicKey | null {
if ( switch (this.type) {
this.type == SystemInstructionLayout.Create || case 'Create':
this.type == SystemInstructionLayout.CreateWithSeed || case 'CreateWithSeed':
this.type == SystemInstructionLayout.WithdrawNonceAccount || case 'WithdrawNonceAccount':
this.type == SystemInstructionLayout.Transfer case 'Transfer':
) {
return this.keys[0].pubkey; return this.keys[0].pubkey;
} default:
return null; return null;
} }
}
/** /**
* The `to` public key of the instruction; * The `to` public key of the instruction;
* returns null if SystemInstructionType does not support this field * returns null if SystemInstructionType does not support this field
*/ */
get toPublicKey(): PublicKey | null { get toPublicKey(): PublicKey | null {
if ( switch (this.type) {
this.type == SystemInstructionLayout.Create || case 'Create':
this.type == SystemInstructionLayout.CreateWithSeed || case 'CreateWithSeed':
this.type == SystemInstructionLayout.WithdrawNonceAccount || case 'WithdrawNonceAccount':
this.type == SystemInstructionLayout.Transfer case 'Transfer':
) {
return this.keys[1].pubkey; return this.keys[1].pubkey;
} default:
return null; return null;
} }
}
/** /**
* The `amount` or `lamports` of the instruction; * The `amount` or `lamports` of the instruction;
* returns null if SystemInstructionType does not support this field * returns null if SystemInstructionType does not support this field
*/ */
get amount(): number | null { get amount(): number | null {
const data = this.type.layout.decode(this.data); const data = SYSTEM_INSTRUCTION_LAYOUTS[this.type].layout.decode(this.data);
if ( switch (this.type) {
this.type == SystemInstructionLayout.Create || case 'Create':
this.type == SystemInstructionLayout.CreateWithSeed || case 'CreateWithSeed':
this.type == SystemInstructionLayout.WithdrawNonceAccount || case 'WithdrawNonceAccount':
this.type == SystemInstructionLayout.Transfer case 'Transfer':
) {
return data.lamports; return data.lamports;
} default:
return null; return null;
} }
}
} }
/** /**
* An enumeration of valid SystemInstructionTypes * An enumeration of valid SystemInstructionType's
* @typedef {'Create' | 'Assign' | 'Transfer' | 'CreateWithSeed'
| 'AdvanceNonceAccount' | 'WithdrawNonceAccount' | 'InitializeNonceAccount'
| 'AuthorizeNonceAccount'} SystemInstructionType
*/ */
const SystemInstructionLayout = Object.freeze({ export type SystemInstructionType = $Keys<typeof SYSTEM_INSTRUCTION_LAYOUTS>;
/**
* An enumeration of valid system InstructionType's
*/
const SYSTEM_INSTRUCTION_LAYOUTS = Object.freeze({
Create: { Create: {
index: 0, index: 0,
layout: BufferLayout.struct([ layout: BufferLayout.struct([
@ -204,7 +219,7 @@ export class SystemProgram {
space: number, space: number,
programId: PublicKey, programId: PublicKey,
): Transaction { ): Transaction {
const type = SystemInstructionLayout.Create; const type = SYSTEM_INSTRUCTION_LAYOUTS.Create;
const data = encodeData(type, { const data = encodeData(type, {
lamports, lamports,
space, space,
@ -229,7 +244,7 @@ export class SystemProgram {
to: PublicKey, to: PublicKey,
lamports: number, lamports: number,
): Transaction { ): Transaction {
const type = SystemInstructionLayout.Transfer; const type = SYSTEM_INSTRUCTION_LAYOUTS.Transfer;
const data = encodeData(type, {lamports}); const data = encodeData(type, {lamports});
return new Transaction().add({ return new Transaction().add({
@ -246,7 +261,7 @@ export class SystemProgram {
* Generate a Transaction that assigns an account to a program * Generate a Transaction that assigns an account to a program
*/ */
static assign(from: PublicKey, programId: PublicKey): Transaction { static assign(from: PublicKey, programId: PublicKey): Transaction {
const type = SystemInstructionLayout.Assign; const type = SYSTEM_INSTRUCTION_LAYOUTS.Assign;
const data = encodeData(type, {programId: programId.toBuffer()}); const data = encodeData(type, {programId: programId.toBuffer()});
return new Transaction().add({ return new Transaction().add({
@ -269,7 +284,7 @@ export class SystemProgram {
space: number, space: number,
programId: PublicKey, programId: PublicKey,
): Transaction { ): Transaction {
const type = SystemInstructionLayout.CreateWithSeed; const type = SYSTEM_INSTRUCTION_LAYOUTS.CreateWithSeed;
const data = encodeData(type, { const data = encodeData(type, {
base: base.toBuffer(), base: base.toBuffer(),
seed, seed,
@ -305,7 +320,7 @@ export class SystemProgram {
this.programId, this.programId,
); );
const type = SystemInstructionLayout.InitializeNonceAccount; const type = SYSTEM_INSTRUCTION_LAYOUTS.InitializeNonceAccount;
const data = encodeData(type, { const data = encodeData(type, {
authorized: authorizedPubkey.toBuffer(), authorized: authorizedPubkey.toBuffer(),
}); });
@ -332,7 +347,7 @@ export class SystemProgram {
nonceAccount: PublicKey, nonceAccount: PublicKey,
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
): TransactionInstruction { ): TransactionInstruction {
const type = SystemInstructionLayout.AdvanceNonceAccount; const type = SYSTEM_INSTRUCTION_LAYOUTS.AdvanceNonceAccount;
const data = encodeData(type); const data = encodeData(type);
const instructionData = { const instructionData = {
keys: [ keys: [
@ -359,7 +374,7 @@ export class SystemProgram {
to: PublicKey, to: PublicKey,
lamports: number, lamports: number,
): Transaction { ): Transaction {
const type = SystemInstructionLayout.WithdrawNonceAccount; const type = SYSTEM_INSTRUCTION_LAYOUTS.WithdrawNonceAccount;
const data = encodeData(type, {lamports}); const data = encodeData(type, {lamports});
return new Transaction().add({ return new Transaction().add({
@ -392,7 +407,7 @@ export class SystemProgram {
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
newAuthorized: PublicKey, newAuthorized: PublicKey,
): Transaction { ): Transaction {
const type = SystemInstructionLayout.AuthorizeNonceAccount; const type = SYSTEM_INSTRUCTION_LAYOUTS.AuthorizeNonceAccount;
const data = encodeData(type, { const data = encodeData(type, {
newAuthorized: newAuthorized.toBuffer(), newAuthorized: newAuthorized.toBuffer(),
}); });

View File

@ -10,7 +10,6 @@ import {
LAMPORTS_PER_SOL, LAMPORTS_PER_SOL,
StakeAuthorizationLayout, StakeAuthorizationLayout,
StakeInstruction, StakeInstruction,
StakeInstructionLayout,
StakeProgram, StakeProgram,
SystemInstruction, SystemInstruction,
SystemProgram, SystemProgram,
@ -197,7 +196,7 @@ test('StakeInstructions', () => {
const stakeInstruction = StakeInstruction.from( const stakeInstruction = StakeInstruction.from(
createWithSeedTransaction.instructions[1], createWithSeedTransaction.instructions[1],
); );
expect(stakeInstruction.type).toEqual(StakeInstructionLayout.Initialize); expect(stakeInstruction.type).toEqual('Initialize');
expect(() => { expect(() => {
StakeInstruction.from(createWithSeedTransaction.instructions[0]); StakeInstruction.from(createWithSeedTransaction.instructions[0]);
@ -216,9 +215,7 @@ test('StakeInstructions', () => {
const anotherStakeInstruction = StakeInstruction.from( const anotherStakeInstruction = StakeInstruction.from(
delegateTransaction.instructions[0], delegateTransaction.instructions[0],
); );
expect(anotherStakeInstruction.type).toEqual( expect(anotherStakeInstruction.type).toEqual('Delegate');
StakeInstructionLayout.DelegateStake,
);
}); });
test('live staking actions', async () => { test('live staking actions', async () => {

View File

@ -249,7 +249,7 @@ test('non-SystemInstruction error', () => {
data: Buffer.from([2, 0, 0, 0]), data: Buffer.from([2, 0, 0, 0]),
}; };
expect(() => { expect(() => {
new SystemInstruction(badProgramId); new SystemInstruction(badProgramId, 'Create');
}).toThrow(); }).toThrow();
const amount = 123; const amount = 123;