feat: add support for more system instructions

This commit is contained in:
Justin Starry 2020-05-09 18:33:36 +08:00 committed by Michael Vines
parent 09d1b7f39f
commit c584fbdf39
5 changed files with 323 additions and 44 deletions

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

@ -578,17 +578,6 @@ declare module '@solana/web3.js' {
programId: PublicKey;
};
export type TransferParams = {
fromPubkey: PublicKey;
toPubkey: PublicKey;
lamports: number;
};
export type AssignParams = {
fromPubkey: PublicKey;
programId: PublicKey;
};
export type CreateAccountWithSeedParams = {
fromPubkey: PublicKey;
newAccountPubkey: PublicKey;
@ -599,6 +588,37 @@ declare module '@solana/web3.js' {
programId: PublicKey;
};
export type AllocateParams = {
accountPubkey: PublicKey;
space: number;
};
export type AllocateWithSeedParams = {
accountPubkey: PublicKey;
basePubkey: PublicKey;
seed: string;
space: number;
programId: PublicKey;
};
export type AssignParams = {
accountPubkey: PublicKey;
programId: PublicKey;
};
export type AssignWithSeedParams = {
accountPubkey: PublicKey;
basePubkey: PublicKey;
seed: string;
programId: PublicKey;
};
export type TransferParams = {
fromPubkey: PublicKey;
toPubkey: PublicKey;
lamports: number;
};
export type CreateNonceAccountParams = {
fromPubkey: PublicKey;
noncePubkey: PublicKey;
@ -642,11 +662,14 @@ declare module '@solana/web3.js' {
static programId: PublicKey;
static createAccount(params: CreateAccountParams): Transaction;
static transfer(params: TransferParams): Transaction;
static assign(params: AssignParams): Transaction;
static createAccountWithSeed(
params: CreateAccountWithSeedParams,
): Transaction;
static allocate(
params: AllocateParams | AllocateWithSeedParams,
): Transaction;
static assign(params: AssignParams | AssignWithSeedParams): Transaction;
static transfer(params: TransferParams): Transaction;
static createNonceAccount(
params: CreateNonceAccountParams | CreateNonceAccountWithSeedParams,
): Transaction;
@ -657,9 +680,12 @@ declare module '@solana/web3.js' {
export type SystemInstructionType =
| 'Create'
| 'Assign'
| 'Transfer'
| 'CreateWithSeed'
| 'Allocate'
| 'AllocateWithSeed'
| 'Assign'
| 'AssignWithSeed'
| 'Transfer'
| 'AdvanceNonceAccount'
| 'WithdrawNonceAccount'
| 'InitializeNonceAccount'
@ -676,11 +702,18 @@ declare module '@solana/web3.js' {
static decodeCreateAccount(
instruction: TransactionInstruction,
): CreateAccountParams;
static decodeTransfer(instruction: TransactionInstruction): TransferParams;
static decodeAssign(instruction: TransactionInstruction): AssignParams;
static decodeCreateWithSeed(
instruction: TransactionInstruction,
): CreateAccountWithSeedParams;
static decodeAllocate(instruction: TransactionInstruction): AllocateParams;
static decodeAllocateWithSeed(
instruction: TransactionInstruction,
): AllocateWithSeedParams;
static decodeAssign(instruction: TransactionInstruction): AssignParams;
static decodeAssignWithSeed(
instruction: TransactionInstruction,
): AssignWithSeedParams;
static decodeTransfer(instruction: TransactionInstruction): TransferParams;
static decodeNonceInitialize(
instruction: TransactionInstruction,
): InitializeNonceParams;

View File

@ -593,17 +593,6 @@ declare module '@solana/web3.js' {
programId: PublicKey,
|};
declare export type TransferParams = {|
fromPubkey: PublicKey,
toPubkey: PublicKey,
lamports: number,
|};
declare export type AssignParams = {|
fromPubkey: PublicKey,
programId: PublicKey,
|};
declare export type CreateAccountWithSeedParams = {|
fromPubkey: PublicKey,
newAccountPubkey: PublicKey,
@ -614,6 +603,37 @@ declare module '@solana/web3.js' {
programId: PublicKey,
|};
declare export type AllocateParams = {|
accountPubkey: PublicKey,
space: number,
|};
declare export type AllocateWithSeedParams = {|
accountPubkey: PublicKey,
basePubkey: PublicKey,
seed: string,
space: number,
programId: PublicKey,
|};
declare export type AssignParams = {|
accountPubkey: PublicKey,
programId: PublicKey,
|};
declare export type AssignWithSeedParams = {|
accountPubkey: PublicKey,
basePubkey: PublicKey,
seed: string,
programId: PublicKey,
|};
declare export type TransferParams = {|
fromPubkey: PublicKey,
toPubkey: PublicKey,
lamports: number,
|};
declare export type CreateNonceAccountParams = {|
fromPubkey: PublicKey,
noncePubkey: PublicKey,
@ -657,11 +677,14 @@ declare module '@solana/web3.js' {
static programId: PublicKey;
static createAccount(params: CreateAccountParams): Transaction;
static transfer(params: TransferParams): Transaction;
static assign(params: AssignParams): Transaction;
static createAccountWithSeed(
params: CreateAccountWithSeedParams,
): Transaction;
static allocate(
params: AllocateParams | AllocateWithSeedParams,
): Transaction;
static assign(params: AssignParams | AssignWithSeedParams): Transaction;
static transfer(params: TransferParams): Transaction;
static createNonceAccount(
params: CreateNonceAccountParams | CreateNonceAccountWithSeedParams,
): Transaction;
@ -672,9 +695,12 @@ declare module '@solana/web3.js' {
declare export type SystemInstructionType =
| 'Create'
| 'Assign'
| 'Transfer'
| 'CreateWithSeed'
| 'Allocate'
| 'AllocateWithSeed'
| 'Assign'
| 'AssignWithSeed'
| 'Transfer'
| 'AdvanceNonceAccount'
| 'WithdrawNonceAccount'
| 'InitializeNonceAccount'
@ -691,11 +717,18 @@ declare module '@solana/web3.js' {
static decodeCreateAccount(
instruction: TransactionInstruction,
): CreateAccountParams;
static decodeTransfer(instruction: TransactionInstruction): TransferParams;
static decodeAssign(instruction: TransactionInstruction): AssignParams;
static decodeCreateWithSeed(
instruction: TransactionInstruction,
): CreateAccountWithSeedParams;
static decodeAllocate(instruction: TransactionInstruction): AllocateParams;
static decodeAllocateWithSeed(
instruction: TransactionInstruction,
): AllocateWithSeedParams;
static decodeAssign(instruction: TransactionInstruction): AssignParams;
static decodeAssignWithSeed(
instruction: TransactionInstruction,
): AssignWithSeedParams;
static decodeTransfer(instruction: TransactionInstruction): TransferParams;
static decodeNonceInitialize(
instruction: TransactionInstruction,
): InitializeNonceParams;

View File

@ -42,11 +42,11 @@ export type TransferParams = {|
/**
* Assign system transaction params
* @typedef {Object} AssignParams
* @property {PublicKey} fromPubkey
* @property {PublicKey} accountPubkey
* @property {PublicKey} programId
*/
export type AssignParams = {|
fromPubkey: PublicKey,
accountPubkey: PublicKey,
programId: PublicKey,
|};
@ -155,6 +155,49 @@ export type AuthorizeNonceParams = {|
newAuthorizedPubkey: PublicKey,
|};
/**
* Allocate account system transaction params
* @typedef {Object} AllocateParams
* @property {PublicKey} accountPubkey
* @property {number} space
*/
export type AllocateParams = {|
accountPubkey: PublicKey,
space: number,
|};
/**
* Allocate account with seed system transaction params
* @typedef {Object} AllocateWithSeedParams
* @property {PublicKey} accountPubkey
* @property {PublicKey} basePubkey
* @property {string} seed
* @property {number} space
* @property {PublicKey} programId
*/
export type AllocateWithSeedParams = {|
accountPubkey: PublicKey,
basePubkey: PublicKey,
seed: string,
space: number,
programId: PublicKey,
|};
/**
* Assign account with seed system transaction params
* @typedef {Object} AssignWithSeedParams
* @property {PublicKey} accountPubkey
* @property {PublicKey} basePubkey
* @property {string} seed
* @property {PublicKey} programId
*/
export type AssignWithSeedParams = {|
accountPubkey: PublicKey,
basePubkey: PublicKey,
seed: string,
programId: PublicKey,
|};
/**
* System Instruction class
*/
@ -226,6 +269,47 @@ export class SystemInstruction {
};
}
/**
* Decode an allocate system instruction and retrieve the instruction params.
*/
static decodeAllocate(instruction: TransactionInstruction): AllocateParams {
this.checkProgramId(instruction.programId);
this.checkKeyLength(instruction.keys, 1);
const {space} = decodeData(
SYSTEM_INSTRUCTION_LAYOUTS.Allocate,
instruction.data,
);
return {
accountPubkey: instruction.keys[0].pubkey,
space,
};
}
/**
* Decode an allocate with seed system instruction and retrieve the instruction params.
*/
static decodeAllocateWithSeed(
instruction: TransactionInstruction,
): AllocateWithSeedParams {
this.checkProgramId(instruction.programId);
this.checkKeyLength(instruction.keys, 1);
const {base, seed, space, programId} = decodeData(
SYSTEM_INSTRUCTION_LAYOUTS.AllocateWithSeed,
instruction.data,
);
return {
accountPubkey: instruction.keys[0].pubkey,
basePubkey: new PublicKey(base),
seed,
space,
programId: new PublicKey(programId),
};
}
/**
* Decode an assign system instruction and retrieve the instruction params.
*/
@ -239,7 +323,29 @@ export class SystemInstruction {
);
return {
fromPubkey: instruction.keys[0].pubkey,
accountPubkey: instruction.keys[0].pubkey,
programId: new PublicKey(programId),
};
}
/**
* Decode an assign with seed system instruction and retrieve the instruction params.
*/
static decodeAssignWithSeed(
instruction: TransactionInstruction,
): AssignWithSeedParams {
this.checkProgramId(instruction.programId);
this.checkKeyLength(instruction.keys, 1);
const {base, seed, programId} = decodeData(
SYSTEM_INSTRUCTION_LAYOUTS.AssignWithSeed,
instruction.data,
);
return {
accountPubkey: instruction.keys[0].pubkey,
basePubkey: new PublicKey(base),
seed,
programId: new PublicKey(programId),
};
}
@ -444,6 +550,32 @@ export const SYSTEM_INSTRUCTION_LAYOUTS = Object.freeze({
Layout.publicKey('authorized'),
]),
},
Allocate: {
index: 8,
layout: BufferLayout.struct([
BufferLayout.u32('instruction'),
BufferLayout.ns64('space'),
]),
},
AllocateWithSeed: {
index: 9,
layout: BufferLayout.struct([
BufferLayout.u32('instruction'),
Layout.publicKey('base'),
Layout.rustString('seed'),
BufferLayout.ns64('space'),
Layout.publicKey('programId'),
]),
},
AssignWithSeed: {
index: 10,
layout: BufferLayout.struct([
BufferLayout.u32('instruction'),
Layout.publicKey('base'),
Layout.rustString('seed'),
Layout.publicKey('programId'),
]),
},
});
/**
@ -498,12 +630,22 @@ export class SystemProgram {
/**
* Generate a Transaction that assigns an account to a program
*/
static assign(params: AssignParams): Transaction {
const type = SYSTEM_INSTRUCTION_LAYOUTS.Assign;
const data = encodeData(type, {programId: params.programId.toBuffer()});
static assign(params: AssignParams | AssignWithSeedParams): Transaction {
let data;
if (params.basePubkey) {
const type = SYSTEM_INSTRUCTION_LAYOUTS.AssignWithSeed;
data = encodeData(type, {
base: params.basePubkey.toBuffer(),
seed: params.seed,
programId: params.programId.toBuffer(),
});
} else {
const type = SYSTEM_INSTRUCTION_LAYOUTS.Assign;
data = encodeData(type, {programId: params.programId.toBuffer()});
}
return new Transaction().add({
keys: [{pubkey: params.fromPubkey, isSigner: true, isWritable: true}],
keys: [{pubkey: params.accountPubkey, isSigner: true, isWritable: true}],
programId: this.programId,
data,
});
@ -666,4 +808,33 @@ export class SystemProgram {
data,
});
}
/**
* Generate a Transaction that allocates space in an account without funding
*/
static allocate(
params: AllocateParams | AllocateWithSeedParams,
): Transaction {
let data;
if (params.basePubkey) {
const type = SYSTEM_INSTRUCTION_LAYOUTS.AllocateWithSeed;
data = encodeData(type, {
base: params.basePubkey.toBuffer(),
seed: params.seed,
space: params.space,
programId: params.programId.toBuffer(),
});
} else {
const type = SYSTEM_INSTRUCTION_LAYOUTS.Allocate;
data = encodeData(type, {
space: params.space,
});
}
return new Transaction().add({
keys: [{pubkey: params.accountPubkey, isSigner: true, isWritable: true}],
programId: this.programId,
data,
});
}
}

View File

@ -132,7 +132,7 @@ test('get program accounts', async () => {
},
]);
let transaction = SystemProgram.assign({
fromPubkey: account0.publicKey,
accountPubkey: account0.publicKey,
programId: programId.publicKey,
});
await sendAndConfirmTransaction(connection, transaction, account0);
@ -176,7 +176,7 @@ test('get program accounts', async () => {
},
]);
transaction = SystemProgram.assign({
fromPubkey: account1.publicKey,
accountPubkey: account1.publicKey,
programId: programId.publicKey,
});

View File

@ -49,9 +49,36 @@ test('transfer', () => {
expect(params).toEqual(SystemInstruction.decodeTransfer(systemInstruction));
});
test('allocate', () => {
const params = {
accountPubkey: new Account().publicKey,
space: 42,
};
const transaction = SystemProgram.allocate(params);
expect(transaction.instructions).toHaveLength(1);
const [systemInstruction] = transaction.instructions;
expect(params).toEqual(SystemInstruction.decodeAllocate(systemInstruction));
});
test('allocateWithSeed', () => {
const params = {
accountPubkey: new Account().publicKey,
basePubkey: new Account().publicKey,
seed: '你好',
space: 42,
programId: new Account().publicKey,
};
const transaction = SystemProgram.allocate(params);
expect(transaction.instructions).toHaveLength(1);
const [systemInstruction] = transaction.instructions;
expect(params).toEqual(
SystemInstruction.decodeAllocateWithSeed(systemInstruction),
);
});
test('assign', () => {
const params = {
fromPubkey: new Account().publicKey,
accountPubkey: new Account().publicKey,
programId: new Account().publicKey,
};
const transaction = SystemProgram.assign(params);
@ -60,6 +87,21 @@ test('assign', () => {
expect(params).toEqual(SystemInstruction.decodeAssign(systemInstruction));
});
test('assignWithSeed', () => {
const params = {
accountPubkey: new Account().publicKey,
basePubkey: new Account().publicKey,
seed: '你好',
programId: new Account().publicKey,
};
const transaction = SystemProgram.assign(params);
expect(transaction.instructions).toHaveLength(1);
const [systemInstruction] = transaction.instructions;
expect(params).toEqual(
SystemInstruction.decodeAssignWithSeed(systemInstruction),
);
});
test('createAccountWithSeed', () => {
const fromPubkey = new Account().publicKey;
const params = {