diff --git a/web3.js/module.d.ts b/web3.js/module.d.ts index 7c531a5504..f1a9fbf152 100644 --- a/web3.js/module.d.ts +++ b/web3.js/module.d.ts @@ -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; diff --git a/web3.js/module.flow.js b/web3.js/module.flow.js index 4fe07793b2..444b7407cf 100644 --- a/web3.js/module.flow.js +++ b/web3.js/module.flow.js @@ -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; diff --git a/web3.js/src/system-program.js b/web3.js/src/system-program.js index c64c3b8800..9fbc2e924b 100644 --- a/web3.js/src/system-program.js +++ b/web3.js/src/system-program.js @@ -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, + }); + } } diff --git a/web3.js/test/connection.test.js b/web3.js/test/connection.test.js index 3f29ee8518..967ba6e373 100644 --- a/web3.js/test/connection.test.js +++ b/web3.js/test/connection.test.js @@ -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, }); diff --git a/web3.js/test/system-program.test.js b/web3.js/test/system-program.test.js index 8aafca0620..1dc4f1d45b 100644 --- a/web3.js/test/system-program.test.js +++ b/web3.js/test/system-program.test.js @@ -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 = {