From 7568df3ccf8f4ae6898c8cc03184030645d60bcc Mon Sep 17 00:00:00 2001 From: Sebastian Pape Date: Fri, 7 Oct 2022 15:26:12 +0200 Subject: [PATCH] v9.7.0: add Token.solana initializeAccountInstruction + closeAccountInstruction --- README.md | 2 + dist/esm/index.js | 46 ++++++++++++++++++- dist/umd/index.js | 46 ++++++++++++++++++- package.json | 2 +- src/platforms/solana/instructions.js | 37 ++++++++++++++- src/platforms/solana/layouts.js | 11 +++++ .../solana/closeAccountInstruction.spec.js | 37 +++++++++++++++ .../initializeAccountInstruction.spec.js | 37 +++++++++++++++ 8 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 tests/units/platforms/solana/closeAccountInstruction.spec.js create mode 100644 tests/units/platforms/solana/initializeAccountInstruction.spec.js diff --git a/README.md b/README.md index a18cac4..9366e01 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,8 @@ Token.solana // findAccount({ token, owner }) // createTransferInstruction({ token, amount, from, to }) // createAssociatedTokenAccountInstruction({ token, owner, payer }) +// initializeAccountInstruction({ account, token, owner }) +// closeAccountInstruction({ account, owner }) ``` ## Development diff --git a/dist/esm/index.js b/dist/esm/index.js index 401df5d..3a0b1c5 100644 --- a/dist/esm/index.js +++ b/dist/esm/index.js @@ -90,6 +90,15 @@ const TOKEN_LAYOUT = struct([ publicKey('closeAuthority') ]); +const INITIALIZE_LAYOUT = struct([ + u8('instruction'), + publicKey('owner') +]); + +const CLOSE_LAYOUT = struct([ + u8('instruction') +]); + const createTransferInstruction = async ({ token, amount, from, to })=>{ let fromTokenAccount = await findProgramAddress({ token, owner: from }); @@ -134,10 +143,45 @@ const createAssociatedTokenAccountInstruction = async ({ token, owner, payer }) }) }; +const initializeAccountInstruction = async ({ account, token, owner })=>{ + + const keys = [ + { pubkey: new PublicKey(account), isSigner: false, isWritable: true }, + { pubkey: new PublicKey(token), isSigner: false, isWritable: false }, + ]; + + const data = Buffer.alloc(INITIALIZE_LAYOUT.span); + INITIALIZE_LAYOUT.encode({ + instruction: 18, // InitializeAccount3 + owner: new PublicKey(owner) + }, data); + + return new TransactionInstruction({ keys, programId: new PublicKey(TOKEN_PROGRAM), data }) +}; + + +const closeAccountInstruction = async ({ account, owner })=>{ + + const keys = [ + { pubkey: new PublicKey(account), isSigner: false, isWritable: true }, + { pubkey: new PublicKey(owner), isSigner: false, isWritable: true }, + { pubkey: new PublicKey(owner), isSigner: true, isWritable: false } + ]; + + const data = Buffer.alloc(CLOSE_LAYOUT.span); + CLOSE_LAYOUT.encode({ + instruction: 9 // CloseAccount + }, data); + + return new TransactionInstruction({ keys, programId: new PublicKey(TOKEN_PROGRAM), data }) +}; + var instructions = /*#__PURE__*/Object.freeze({ __proto__: null, createTransferInstruction: createTransferInstruction, - createAssociatedTokenAccountInstruction: createAssociatedTokenAccountInstruction + createAssociatedTokenAccountInstruction: createAssociatedTokenAccountInstruction, + initializeAccountInstruction: initializeAccountInstruction, + closeAccountInstruction: closeAccountInstruction }); var allowanceOnEVM = ({ blockchain, address, api, owner, spender })=>{ diff --git a/dist/umd/index.js b/dist/umd/index.js index abeb8ac..70354b9 100644 --- a/dist/umd/index.js +++ b/dist/umd/index.js @@ -91,6 +91,15 @@ solanaWeb3_js.publicKey('closeAuthority') ]); + const INITIALIZE_LAYOUT = solanaWeb3_js.struct([ + solanaWeb3_js.u8('instruction'), + solanaWeb3_js.publicKey('owner') + ]); + + const CLOSE_LAYOUT = solanaWeb3_js.struct([ + solanaWeb3_js.u8('instruction') + ]); + const createTransferInstruction = async ({ token, amount, from, to })=>{ let fromTokenAccount = await findProgramAddress({ token, owner: from }); @@ -135,10 +144,45 @@ }) }; + const initializeAccountInstruction = async ({ account, token, owner })=>{ + + const keys = [ + { pubkey: new solanaWeb3_js.PublicKey(account), isSigner: false, isWritable: true }, + { pubkey: new solanaWeb3_js.PublicKey(token), isSigner: false, isWritable: false }, + ]; + + const data = solanaWeb3_js.Buffer.alloc(INITIALIZE_LAYOUT.span); + INITIALIZE_LAYOUT.encode({ + instruction: 18, // InitializeAccount3 + owner: new solanaWeb3_js.PublicKey(owner) + }, data); + + return new solanaWeb3_js.TransactionInstruction({ keys, programId: new solanaWeb3_js.PublicKey(TOKEN_PROGRAM), data }) + }; + + + const closeAccountInstruction = async ({ account, owner })=>{ + + const keys = [ + { pubkey: new solanaWeb3_js.PublicKey(account), isSigner: false, isWritable: true }, + { pubkey: new solanaWeb3_js.PublicKey(owner), isSigner: false, isWritable: true }, + { pubkey: new solanaWeb3_js.PublicKey(owner), isSigner: true, isWritable: false } + ]; + + const data = solanaWeb3_js.Buffer.alloc(CLOSE_LAYOUT.span); + CLOSE_LAYOUT.encode({ + instruction: 9 // CloseAccount + }, data); + + return new solanaWeb3_js.TransactionInstruction({ keys, programId: new solanaWeb3_js.PublicKey(TOKEN_PROGRAM), data }) + }; + var instructions = /*#__PURE__*/Object.freeze({ __proto__: null, createTransferInstruction: createTransferInstruction, - createAssociatedTokenAccountInstruction: createAssociatedTokenAccountInstruction + createAssociatedTokenAccountInstruction: createAssociatedTokenAccountInstruction, + initializeAccountInstruction: initializeAccountInstruction, + closeAccountInstruction: closeAccountInstruction }); var allowanceOnEVM = ({ blockchain, address, api, owner, spender })=>{ diff --git a/package.json b/package.json index 2b09552..879e591 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@depay/web3-tokens", "moduleName": "Web3Tokens", - "version": "9.6.0", + "version": "9.7.0", "description": "JavaScript library providing basic functionalities to interact with web3 tokens.", "main": "dist/umd/index.js", "module": "dist/esm/index.js", diff --git a/src/platforms/solana/instructions.js b/src/platforms/solana/instructions.js index af6bd22..d751ff5 100644 --- a/src/platforms/solana/instructions.js +++ b/src/platforms/solana/instructions.js @@ -1,7 +1,7 @@ import findProgramAddress from './findProgramAddress' import { SystemProgram, PublicKey, TransactionInstruction, Buffer, BN } from '@depay/solana-web3.js' import { TOKEN_PROGRAM, ASSOCIATED_TOKEN_PROGRAM } from './constants' -import { TRANSFER_LAYOUT } from './layouts' +import { TRANSFER_LAYOUT, INITIALIZE_LAYOUT, CLOSE_LAYOUT } from './layouts' const createTransferInstruction = async ({ token, amount, from, to })=>{ @@ -47,7 +47,42 @@ const createAssociatedTokenAccountInstruction = async ({ token, owner, payer }) }) } +const initializeAccountInstruction = async ({ account, token, owner })=>{ + + const keys = [ + { pubkey: new PublicKey(account), isSigner: false, isWritable: true }, + { pubkey: new PublicKey(token), isSigner: false, isWritable: false }, + ] + + const data = Buffer.alloc(INITIALIZE_LAYOUT.span) + INITIALIZE_LAYOUT.encode({ + instruction: 18, // InitializeAccount3 + owner: new PublicKey(owner) + }, data) + + return new TransactionInstruction({ keys, programId: new PublicKey(TOKEN_PROGRAM), data }) +} + + +const closeAccountInstruction = async ({ account, owner })=>{ + + const keys = [ + { pubkey: new PublicKey(account), isSigner: false, isWritable: true }, + { pubkey: new PublicKey(owner), isSigner: false, isWritable: true }, + { pubkey: new PublicKey(owner), isSigner: true, isWritable: false } + ] + + const data = Buffer.alloc(CLOSE_LAYOUT.span) + CLOSE_LAYOUT.encode({ + instruction: 9 // CloseAccount + }, data) + + return new TransactionInstruction({ keys, programId: new PublicKey(TOKEN_PROGRAM), data }) +} + export { createTransferInstruction, createAssociatedTokenAccountInstruction, + initializeAccountInstruction, + closeAccountInstruction, } diff --git a/src/platforms/solana/layouts.js b/src/platforms/solana/layouts.js index 6849761..a1e3fea 100644 --- a/src/platforms/solana/layouts.js +++ b/src/platforms/solana/layouts.js @@ -69,9 +69,20 @@ const TOKEN_LAYOUT = struct([ publicKey('closeAuthority') ]) +const INITIALIZE_LAYOUT = struct([ + u8('instruction'), + publicKey('owner') +]) + +const CLOSE_LAYOUT = struct([ + u8('instruction') +]) + export { MINT_LAYOUT, METADATA_LAYOUT, TRANSFER_LAYOUT, TOKEN_LAYOUT, + INITIALIZE_LAYOUT, + CLOSE_LAYOUT, } diff --git a/tests/units/platforms/solana/closeAccountInstruction.spec.js b/tests/units/platforms/solana/closeAccountInstruction.spec.js new file mode 100644 index 0000000..948018d --- /dev/null +++ b/tests/units/platforms/solana/closeAccountInstruction.spec.js @@ -0,0 +1,37 @@ +import { mock, resetMocks } from '@depay/web3-mock' +import { resetCache, provider } from '@depay/web3-client' +import { supported } from 'src/blockchains' +import { SystemProgram } from '@depay/solana-web3.js' +import { Token } from 'src' +import { TOKEN_PROGRAM } from 'src/platforms/solana/constants' + +describe('closeAccountInstruction', () => { + + supported.solana.forEach((blockchain)=>{ + + beforeEach(resetCache) + beforeEach(resetMocks) + + it('provides a close account instruction', async ()=> { + + let account = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' + let owner = '2UgCJaHU5y8NC4uWQcZYeV9a5RyYLF7iKYCybCsdFFD1' + + mock({ + blockchain, + provider: provider(blockchain), + }) + + let instruction = await Token.solana.closeAccountInstruction({ + account, + owner, + }) + + expect(instruction.keys[0].pubkey.toString()).toEqual(account) + expect(instruction.keys[1].pubkey.toString()).toEqual(owner) + expect(instruction.keys[2].pubkey.toString()).toEqual(owner) + expect(instruction.programId.toString()).toEqual(Token.solana.TOKEN_PROGRAM) + }) + }) +}) + diff --git a/tests/units/platforms/solana/initializeAccountInstruction.spec.js b/tests/units/platforms/solana/initializeAccountInstruction.spec.js new file mode 100644 index 0000000..49914ce --- /dev/null +++ b/tests/units/platforms/solana/initializeAccountInstruction.spec.js @@ -0,0 +1,37 @@ +import { mock, resetMocks } from '@depay/web3-mock' +import { resetCache, provider } from '@depay/web3-client' +import { supported } from 'src/blockchains' +import { SystemProgram } from '@depay/solana-web3.js' +import { Token } from 'src' +import { TOKEN_PROGRAM } from 'src/platforms/solana/constants' + +describe('initializeAccountInstruction', () => { + + supported.solana.forEach((blockchain)=>{ + + beforeEach(resetCache) + beforeEach(resetMocks) + + it('provides a initialize token account instruction', async ()=> { + + let account = 'EFjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' + let token = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' + let owner = '2UgCJaHU5y8NC4uWQcZYeV9a5RyYLF7iKYCybCsdFFD1' + + mock({ + blockchain, + provider: provider(blockchain), + }) + + let instruction = await Token.solana.initializeAccountInstruction({ + account, + token, + owner, + }) + + expect(instruction.keys[0].pubkey.toString()).toEqual(account) + expect(instruction.keys[1].pubkey.toString()).toEqual(token) + expect(instruction.programId.toString()).toEqual(Token.solana.TOKEN_PROGRAM) + }) + }) +})