diff --git a/Cargo.toml b/Cargo.toml index 3e79eb10..81c2df58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,6 @@ members = [ "basics/counter/native/program", "basics/counter/pinocchio/program", "basics/counter/anchor/programs/counter_anchor", - "basics/counter/mpl-stack", "basics/create-account/native/program", "basics/create-account/pinocchio/program", "basics/create-account/anchor/programs/create-system-account", diff --git a/basics/counter/mpl-stack/.solitarc.js b/basics/counter/mpl-stack/.solitarc.js deleted file mode 100644 index 8ea5faec..00000000 --- a/basics/counter/mpl-stack/.solitarc.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check -const path = require("node:path"); -const programDir = path.join(__dirname); -const idlDir = path.join(__dirname, "idl"); -const sdkDir = path.join(__dirname, "ts", "generated"); -const binaryInstallDir = path.join(__dirname, "target", "solita"); - -module.exports = { - idlGenerator: "shank", - programName: "counter_mpl_stack", - programId: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS", - idlDir, - sdkDir, - binaryInstallDir, - programDir, -}; diff --git a/basics/counter/mpl-stack/Cargo.toml b/basics/counter/mpl-stack/Cargo.toml deleted file mode 100644 index cc936565..00000000 --- a/basics/counter/mpl-stack/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "counter-mpl-stack" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = ["cdylib", "lib"] - -[features] -no-entrypoint = [] -cpi = ["no-entrypoint"] -default = [] -custom-heap = [] -custom-panic = [] - -[dependencies] -borsh = "1.6" -shank = "0.4.8" -solana-program = "4.0" - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] } diff --git a/basics/counter/mpl-stack/README.md b/basics/counter/mpl-stack/README.md deleted file mode 100644 index bf6c733f..00000000 --- a/basics/counter/mpl-stack/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Counter: MPL Stack - -A Solana-native counter built using the MPL (Metaplex) stack. - -## Setup - -1. Build the [program](https://solana.com/docs/terminology#program): `cargo build-sbf` -2. Build the IDL: `shank build` -3. Build the TypeScript SDK: `pnpm solita` - - Temporary workaround: edit `ts/generated/accounts/Counter.ts` line 58 to - `const accountInfo = await connection.getAccountInfo(address, { commitment: "confirmed" });` - so that the tests pass. Future Solita versions will fix this. -4. Run tests: `pnpm test` diff --git a/basics/counter/mpl-stack/idl/counter_mpl_stack.json b/basics/counter/mpl-stack/idl/counter_mpl_stack.json deleted file mode 100644 index 3369f316..00000000 --- a/basics/counter/mpl-stack/idl/counter_mpl_stack.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "version": "0.1.0", - "name": "counter_mpl_stack", - "instructions": [ - { - "name": "Increment", - "accounts": [ - { - "name": "counter", - "isMut": true, - "isSigner": false, - "desc": "Counter account to increment" - } - ], - "args": [], - "discriminant": { - "type": "u8", - "value": 0 - } - } - ], - "accounts": [ - { - "name": "Counter", - "type": { - "kind": "struct", - "fields": [ - { - "name": "count", - "type": "u64" - } - ] - } - } - ], - "metadata": { - "origin": "shank", - "address": "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS", - "binaryVersion": "0.0.8", - "libVersion": "0.0.8" - } -} diff --git a/basics/counter/mpl-stack/idl/counter_solana_native.json b/basics/counter/mpl-stack/idl/counter_solana_native.json deleted file mode 100644 index 97b709b9..00000000 --- a/basics/counter/mpl-stack/idl/counter_solana_native.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "version": "0.1.0", - "name": "counter_solana_native", - "instructions": [ - { - "name": "Increment", - "accounts": [], - "args": [], - "discriminant": { - "type": "u8", - "value": 0 - } - } - ], - "accounts": [ - { - "name": "Counter", - "type": { - "kind": "struct", - "fields": [ - { - "name": "count", - "type": "u64" - } - ] - } - } - ], - "metadata": { - "origin": "shank", - "address": "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS" - } -} diff --git a/basics/counter/mpl-stack/jest.config.js b/basics/counter/mpl-stack/jest.config.js deleted file mode 100644 index 4dd7c478..00000000 --- a/basics/counter/mpl-stack/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - preset: "ts-jest/presets/default", - testEnvironment: "node", - testTimeout: 100000, - resolver: "ts-jest-resolver", -}; diff --git a/basics/counter/mpl-stack/package.json b/basics/counter/mpl-stack/package.json deleted file mode 100644 index 9097c339..00000000 --- a/basics/counter/mpl-stack/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "counter-mpl-stack", - "version": "0.1.0", - "description": "Counter program written using MPL tooling", - "main": "index.js", - "author": "ngundotra", - "license": "Apache-2.0", - "private": false, - "scripts": { - "start-validator": "solana-test-validator --reset --quiet --bpf-program Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS ./target/deploy/counter_solana_native.so", - "run-tests": "jest tests --detectOpenHandles", - "test": "start-server-and-test start-validator http://localhost:8899/health run-tests" - }, - "devDependencies": { - "@types/bn.js": "^5.1.1", - "@types/jest": "^29.0.0", - "chai": "^4.3.6", - "jest": "^29.0.2", - "start-server-and-test": "^1.14.0", - "ts-jest": "^28.0.8", - "ts-jest-resolver": "^2.0.0", - "ts-node": "^10.9.1", - "typescript": "^4.8.2" - }, - "dependencies": { - "@metaplex-foundation/beet": "^0.6.1", - "@metaplex-foundation/solita": "^0.15.2", - "@solana/web3.js": "^1.98.4" - } -} diff --git a/basics/counter/mpl-stack/src/lib.rs b/basics/counter/mpl-stack/src/lib.rs deleted file mode 100644 index 4fd7da61..00000000 --- a/basics/counter/mpl-stack/src/lib.rs +++ /dev/null @@ -1,65 +0,0 @@ -use borsh::{BorshDeserialize, BorshSerialize}; -use shank::ShankInstruction; -use solana_program::{ - account_info::{next_account_info, AccountInfo}, - declare_id, - entrypoint::ProgramResult, - msg, - program_error::ProgramError, - pubkey::Pubkey, -}; - -mod state; -use state::*; - -declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"); - -#[cfg(not(feature = "no-entrypoint"))] -use solana_program::entrypoint; - -#[cfg(not(feature = "no-entrypoint"))] -entrypoint!(process_instruction); - -#[derive(ShankInstruction, BorshDeserialize, BorshSerialize)] -pub enum Instruction { - #[account(0, writable, name = "counter", desc = "Counter account to increment")] - Increment, -} - -pub fn process_instruction( - _program_id: &Pubkey, - accounts: &[AccountInfo], - instruction_data: &[u8], -) -> ProgramResult { - let (instruction_discriminant, instruction_data_inner) = instruction_data.split_at(1); - match instruction_discriminant[0] { - 0 => { - msg!("Instruction: Increment"); - process_increment_counter(accounts, instruction_data_inner)?; - } - _ => { - msg!("Error: unknown instruction") - } - } - Ok(()) -} - -pub fn process_increment_counter( - accounts: &[AccountInfo], - _instruction_data: &[u8], -) -> Result<(), ProgramError> { - let account_info_iter = &mut accounts.iter(); - - let counter_account = next_account_info(account_info_iter)?; - assert!( - counter_account.is_writable, - "Counter account must be writable" - ); - - let mut counter = Counter::try_from_slice(&counter_account.try_borrow_mut_data()?)?; - counter.count += 1; - counter.serialize(&mut *counter_account.data.borrow_mut())?; - - msg!("Counter state incremented to {:?}", counter.count); - Ok(()) -} diff --git a/basics/counter/mpl-stack/src/state.rs b/basics/counter/mpl-stack/src/state.rs deleted file mode 100644 index 745af6f2..00000000 --- a/basics/counter/mpl-stack/src/state.rs +++ /dev/null @@ -1,7 +0,0 @@ -use borsh::{BorshDeserialize, BorshSerialize}; -use shank::ShankAccount; - -#[derive(ShankAccount, BorshSerialize, BorshDeserialize, Debug, Clone)] -pub struct Counter { - pub count: u64, -} diff --git a/basics/counter/mpl-stack/tests/counter.test.ts b/basics/counter/mpl-stack/tests/counter.test.ts deleted file mode 100644 index dc345a80..00000000 --- a/basics/counter/mpl-stack/tests/counter.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import type { bignum } from "@metaplex-foundation/beet"; -import { - Connection, - Keypair, - LAMPORTS_PER_SOL, - SystemProgram, - sendAndConfirmTransaction, - Transaction, - type TransactionInstruction, -} from "@solana/web3.js"; -import { BN } from "bn.js"; -import { assert } from "chai"; - -import { Counter, createIncrementInstruction, PROGRAM_ID } from "../ts"; - -function convertBignumToNumber(bignum: bignum): number { - return new BN(bignum).toNumber(); -} - -describe("Counter Solana Native", () => { - const connection = new Connection("http://localhost:8899"); - - it("Test allocate counter + increment tx", async () => { - // Randomly generate our wallet - const payerKeypair = Keypair.generate(); - const payer = payerKeypair.publicKey; - - // Randomly generate the account key - // to sign for setting up the Counter state - const counterKeypair = Keypair.generate(); - const counter = counterKeypair.publicKey; - - // Airdrop our wallet 1 Sol - await connection.requestAirdrop(payer, LAMPORTS_PER_SOL); - - // Create a TransactionInstruction to interact with our counter program - const allocIx: TransactionInstruction = SystemProgram.createAccount({ - fromPubkey: payer, - newAccountPubkey: counter, - lamports: await connection.getMinimumBalanceForRentExemption(Counter.byteSize), - space: Counter.byteSize, - programId: PROGRAM_ID, - }); - const incrementIx: TransactionInstruction = createIncrementInstruction({ - counter, - }); - const tx = new Transaction().add(allocIx).add(incrementIx); - - // Explicitly set the feePayer to be our wallet (this is set to first signer by default) - tx.feePayer = payer; - - // Fetch a "timestamp" so validators know this is a recent transaction - tx.recentBlockhash = (await connection.getLatestBlockhash("confirmed")).blockhash; - - // Send transaction to network (local network) - await sendAndConfirmTransaction(connection, tx, [payerKeypair, counterKeypair], { - skipPreflight: true, - commitment: "confirmed", - }); - - // Get the counter account info from network - const count = (await Counter.fromAccountAddress(connection, counter)).count; - assert(new BN(count).toNumber() === 1, "Expected count to have been 1"); - console.log(`[alloc+increment] count is: ${count}`); - }); - it("Test allocate tx and increment tx", async () => { - const payerKeypair = Keypair.generate(); - const payer = payerKeypair.publicKey; - - const counterKeypair = Keypair.generate(); - const counter = counterKeypair.publicKey; - - await connection.requestAirdrop(payer, LAMPORTS_PER_SOL); - - // Check allocate tx - const allocIx: TransactionInstruction = SystemProgram.createAccount({ - fromPubkey: payer, - newAccountPubkey: counter, - lamports: await connection.getMinimumBalanceForRentExemption(Counter.byteSize), - space: Counter.byteSize, - programId: PROGRAM_ID, - }); - let tx = new Transaction().add(allocIx); - tx.feePayer = payer; - tx.recentBlockhash = (await connection.getLatestBlockhash("confirmed")).blockhash; - await sendAndConfirmTransaction(connection, tx, [payerKeypair, counterKeypair], { - skipPreflight: true, - commitment: "confirmed", - }); - - let count = (await Counter.fromAccountAddress(connection, counter)).count; - assert(convertBignumToNumber(count) === 0, "Expected count to have been 0"); - console.log(`[allocate] count is: ${count}`); - - // Check increment tx - const incrementIx: TransactionInstruction = createIncrementInstruction({ - counter, - }); - tx = new Transaction().add(incrementIx); - tx.feePayer = payer; - tx.recentBlockhash = (await connection.getLatestBlockhash("confirmed")).blockhash; - await sendAndConfirmTransaction(connection, tx, [payerKeypair], { - skipPreflight: true, - commitment: "confirmed", - }); - - count = (await Counter.fromAccountAddress(connection, counter)).count; - assert(convertBignumToNumber(count) === 1, "Expected count to have been 1"); - console.log(`[increment] count is: ${count}`); - }); -}); diff --git a/basics/counter/mpl-stack/ts/generated/accounts/Counter.ts b/basics/counter/mpl-stack/ts/generated/accounts/Counter.ts deleted file mode 100644 index 159e2972..00000000 --- a/basics/counter/mpl-stack/ts/generated/accounts/Counter.ts +++ /dev/null @@ -1,145 +0,0 @@ -/** - * This code was GENERATED using the solita package. - * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. - * - * See: https://github.com/metaplex-foundation/solita - */ - -import * as beet from "@metaplex-foundation/beet"; -import * as beetSolana from "@metaplex-foundation/beet-solana"; -import * as web3 from "@solana/web3.js"; - -/** - * Arguments used to create {@link Counter} - * @category Accounts - * @category generated - */ -export type CounterArgs = { - count: beet.bignum; -}; -/** - * Holds the data for the {@link Counter} Account and provides de/serialization - * functionality for that data - * - * @category Accounts - * @category generated - */ -export class Counter implements CounterArgs { - private constructor(readonly count: beet.bignum) {} - - /** - * Creates a {@link Counter} instance from the provided args. - */ - static fromArgs(args: CounterArgs) { - return new Counter(args.count); - } - - /** - * Deserializes the {@link Counter} from the data of the provided {@link web3.AccountInfo}. - * @returns a tuple of the account data and the offset up to which the buffer was read to obtain it. - */ - static fromAccountInfo(accountInfo: web3.AccountInfo, offset = 0): [Counter, number] { - return Counter.deserialize(accountInfo.data, offset); - } - - /** - * Retrieves the account info from the provided address and deserializes - * the {@link Counter} from its data. - * - * @throws Error if no account info is found at the address or if deserialization fails - */ - static async fromAccountAddress(connection: web3.Connection, address: web3.PublicKey): Promise { - const accountInfo = await connection.getAccountInfo(address, { - commitment: "confirmed", - }); - if (accountInfo == null) { - throw new Error(`Unable to find Counter account at ${address}`); - } - return Counter.fromAccountInfo(accountInfo, 0)[0]; - } - - /** - * Provides a {@link web3.Connection.getProgramAccounts} config builder, - * to fetch accounts matching filters that can be specified via that builder. - * - * @param programId - the program that owns the accounts we are filtering - */ - static gpaBuilder(programId: web3.PublicKey = new web3.PublicKey("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS")) { - return beetSolana.GpaBuilder.fromStruct(programId, counterBeet); - } - - /** - * Deserializes the {@link Counter} from the provided data Buffer. - * @returns a tuple of the account data and the offset up to which the buffer was read to obtain it. - */ - static deserialize(buf: Buffer, offset = 0): [Counter, number] { - return counterBeet.deserialize(buf, offset); - } - - /** - * Serializes the {@link Counter} into a Buffer. - * @returns a tuple of the created Buffer and the offset up to which the buffer was written to store it. - */ - serialize(): [Buffer, number] { - return counterBeet.serialize(this); - } - - /** - * Returns the byteSize of a {@link Buffer} holding the serialized data of - * {@link Counter} - */ - static get byteSize() { - return counterBeet.byteSize; - } - - /** - * Fetches the minimum balance needed to exempt an account holding - * {@link Counter} data from rent - * - * @param connection used to retrieve the rent exemption information - */ - static async getMinimumBalanceForRentExemption( - connection: web3.Connection, - commitment?: web3.Commitment, - ): Promise { - return connection.getMinimumBalanceForRentExemption(Counter.byteSize, commitment); - } - - /** - * Determines if the provided {@link Buffer} has the correct byte size to - * hold {@link Counter} data. - */ - static hasCorrectByteSize(buf: Buffer, offset = 0) { - return buf.byteLength - offset === Counter.byteSize; - } - - /** - * Returns a readable version of {@link Counter} properties - * and can be used to convert to JSON and/or logging - */ - pretty() { - return { - count: (() => { - const x = <{ toNumber: () => number }>this.count; - if (typeof x.toNumber === "function") { - try { - return x.toNumber(); - } catch (_) { - return x; - } - } - return x; - })(), - }; - } -} - -/** - * @category Accounts - * @category generated - */ -export const counterBeet = new beet.BeetStruct( - [["count", beet.u64]], - Counter.fromArgs, - "Counter", -); diff --git a/basics/counter/mpl-stack/ts/generated/accounts/index.ts b/basics/counter/mpl-stack/ts/generated/accounts/index.ts deleted file mode 100644 index 4a738244..00000000 --- a/basics/counter/mpl-stack/ts/generated/accounts/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./Counter"; - -import { Counter } from "./Counter"; - -export const accountProviders = { Counter }; diff --git a/basics/counter/mpl-stack/ts/generated/index.ts b/basics/counter/mpl-stack/ts/generated/index.ts deleted file mode 100644 index 8a3d9703..00000000 --- a/basics/counter/mpl-stack/ts/generated/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { PublicKey } from "@solana/web3.js"; - -export * from "./accounts"; -export * from "./instructions"; - -/** - * Program address - * - * @category constants - * @category generated - */ -export const PROGRAM_ADDRESS = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"; - -/** - * Program public key - * - * @category constants - * @category generated - */ -export const PROGRAM_ID = new PublicKey(PROGRAM_ADDRESS); diff --git a/basics/counter/mpl-stack/ts/generated/instructions/Increment.ts b/basics/counter/mpl-stack/ts/generated/instructions/Increment.ts deleted file mode 100644 index afc81456..00000000 --- a/basics/counter/mpl-stack/ts/generated/instructions/Increment.ts +++ /dev/null @@ -1,62 +0,0 @@ -/** - * This code was GENERATED using the solita package. - * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. - * - * See: https://github.com/metaplex-foundation/solita - */ - -import * as beet from "@metaplex-foundation/beet"; -import * as web3 from "@solana/web3.js"; - -/** - * @category Instructions - * @category Increment - * @category generated - */ -export const IncrementStruct = new beet.BeetArgsStruct<{ - instructionDiscriminator: number; -}>([["instructionDiscriminator", beet.u8]], "IncrementInstructionArgs"); -/** - * Accounts required by the _Increment_ instruction - * - * @property [_writable_] counter Counter account to increment - * @category Instructions - * @category Increment - * @category generated - */ -export type IncrementInstructionAccounts = { - counter: web3.PublicKey; -}; - -export const incrementInstructionDiscriminator = 0; - -/** - * Creates a _Increment_ instruction. - * - * @param accounts that will be accessed while the instruction is processed - * @category Instructions - * @category Increment - * @category generated - */ -export function createIncrementInstruction( - accounts: IncrementInstructionAccounts, - programId = new web3.PublicKey("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"), -) { - const [data] = IncrementStruct.serialize({ - instructionDiscriminator: incrementInstructionDiscriminator, - }); - const keys: web3.AccountMeta[] = [ - { - pubkey: accounts.counter, - isWritable: true, - isSigner: false, - }, - ]; - - const ix = new web3.TransactionInstruction({ - programId, - keys, - data, - }); - return ix; -} diff --git a/basics/counter/mpl-stack/ts/generated/instructions/index.ts b/basics/counter/mpl-stack/ts/generated/instructions/index.ts deleted file mode 100644 index 84936e74..00000000 --- a/basics/counter/mpl-stack/ts/generated/instructions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./Increment"; diff --git a/basics/counter/mpl-stack/ts/index.ts b/basics/counter/mpl-stack/ts/index.ts deleted file mode 100644 index e84c86c6..00000000 --- a/basics/counter/mpl-stack/ts/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./generated";