From 25294dad089bc0822c404912b02fcfaf437ce998 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Mon, 8 Dec 2025 10:52:29 -0800 Subject: [PATCH 1/5] begin removing solana program --- Cargo.lock | 188 +++++++++++++++++++++++++++------ Cargo.toml | 7 +- lib/Cargo.toml | 7 +- lib/src/account/close.rs | 24 +++-- lib/src/account/deserialize.rs | 29 +++-- lib/src/account/lamports.rs | 32 +++--- lib/src/account/validation.rs | 79 ++++++++------ lib/src/lib.rs | 33 ++++-- lib/src/utils.rs | 7 +- 9 files changed, 284 insertions(+), 122 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3cc0086..5c39ad0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -982,11 +982,29 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "five8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f76610e969fa1784327ded240f1e28a3fd9520c9cec93b636fcf62dd37f772" +dependencies = [ + "five8_core", +] + [[package]] name = "five8_const" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b4f62f0f8ca357f93ae90c8c2dd1041a1f665fde2f889ea9b1787903829015" +checksum = "26dec3da8bc3ef08f2c04f61eab298c3ab334523e55f076354d6d6f613799a7b" +dependencies = [ + "five8_core", +] + +[[package]] +name = "five8_const" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a0f1728185f277989ca573a402716ae0beaaea3f76a8ff87ef9dd8fb19436c5" dependencies = [ "five8_core", ] @@ -1820,6 +1838,33 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "pinocchio" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b971851087bc3699b001954ad02389d50c41405ece3548cbcafc88b3e20017a" + +[[package]] +name = "pinocchio-pubkey" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0225638cadcbebae8932cb7f49cb5da7c15c21beb19f048f05a5ca7d93f065" +dependencies = [ + "five8_const 0.1.4", + "pinocchio", + "sha2-const-stable", +] + +[[package]] +name = "pinocchio-system" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2a6dad40b5e75d1486f021619c4bd504c34c1362c9b94ed7fa525b1cc63cc" +dependencies = [ + "pinocchio", + "pinocchio-pubkey", +] + [[package]] name = "pkg-config" version = "0.3.31" @@ -2188,6 +2233,12 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2-const-stable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9" + [[package]] name = "sha3" version = "0.10.8" @@ -2250,11 +2301,35 @@ checksum = "fe9a5a802bc6ab2ba6a9d77580b038e7c2409932074f14fe35eaa64894a53c1e" dependencies = [ "bincode", "serde", - "solana-program-error", + "solana-program-error 2.1.9", "solana-program-memory", "solana-pubkey", ] +[[package]] +name = "solana-account-view" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37ca34c37f92ee341b73d5ce7c8ef5bb38e9a87955b4bd343c63fa18b149215" +dependencies = [ + "solana-address", + "solana-program-error 3.0.0", +] + +[[package]] +name = "solana-address" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37320fd2945c5d654b2c6210624a52d66c3f1f73b653ed211ab91a703b35bdd" +dependencies = [ + "curve25519-dalek 4.1.3", + "five8", + "five8_const 1.0.0", + "solana-define-syscall 4.0.1", + "solana-program-error 3.0.0", + "solana-sha256-hasher 3.1.0", +] + [[package]] name = "solana-atomic-u64" version = "2.1.9" @@ -2372,9 +2447,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1b66925890e4108d10df357940da32ae01eea68d07b8da816eec4b93519db9d" dependencies = [ "solana-account-info", - "solana-define-syscall", + "solana-define-syscall 2.1.9", "solana-instruction", - "solana-program-error", + "solana-program-error 2.1.9", "solana-pubkey", "solana-stable-layout", ] @@ -2407,6 +2482,12 @@ version = "2.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d145184b5a9ada39c4cf1f5610cb33d342767c58f7fc87bd3b5ea51f183c2937" +[[package]] +name = "solana-define-syscall" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e5b1c0bc1d4a4d10c88a4100499d954c09d3fecfae4912c1a074dff68b1738" + [[package]] name = "solana-derivation-path" version = "2.1.9" @@ -2439,9 +2520,9 @@ dependencies = [ "lazy_static", "solana-clock", "solana-epoch-schedule", - "solana-hash", + "solana-hash 2.1.9", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.1.9", ] [[package]] @@ -2473,6 +2554,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "solana-hash" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5d48a6ee7b91fc7b998944ab026ed7b3e2fc8ee3bc58452644a86c2648152f" + [[package]] name = "solana-inflation" version = "2.1.9" @@ -2496,11 +2583,23 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-define-syscall", + "solana-define-syscall 2.1.9", "solana-pubkey", "wasm-bindgen", ] +[[package]] +name = "solana-instruction-view" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60147e4d0a4620013df40bf30a86dd299203ff12fcb8b593cd51014fce0875d8" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-define-syscall 4.0.1", + "solana-program-error 3.0.0", +] + [[package]] name = "solana-last-restart-slot" version = "2.1.9" @@ -2519,7 +2618,7 @@ version = "2.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4818fcc8b1fa46f1d0c698a0645e0cf693baf4ab5654001fcaff4623187016cf" dependencies = [ - "solana-define-syscall", + "solana-define-syscall 2.1.9", ] [[package]] @@ -2571,7 +2670,7 @@ dependencies = [ "console_error_panic_hook", "console_log", "curve25519-dalek 4.1.3", - "five8_const", + "five8_const 0.1.4", "getrandom 0.2.15", "js-sys", "lazy_static", @@ -2594,16 +2693,16 @@ dependencies = [ "solana-clock", "solana-cpi", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.1.9", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.1.9", "solana-instruction", "solana-last-restart-slot", "solana-msg", "solana-native-token", "solana-program-entrypoint", - "solana-program-error", + "solana-program-error 2.1.9", "solana-program-memory", "solana-program-option", "solana-program-pack", @@ -2614,7 +2713,7 @@ dependencies = [ "solana-secp256k1-recover", "solana-serde-varint", "solana-serialize-utils", - "solana-sha256-hasher", + "solana-sha256-hasher 2.1.9", "solana-short-vec", "solana-slot-hashes", "solana-slot-history", @@ -2633,7 +2732,7 @@ checksum = "8f296f87584dbc684ed1fb00f849803358d97f663ec2829165052d50c2d30de3" dependencies = [ "solana-account-info", "solana-msg", - "solana-program-error", + "solana-program-error 2.1.9", "solana-pubkey", ] @@ -2653,6 +2752,12 @@ dependencies = [ "solana-pubkey", ] +[[package]] +name = "solana-program-error" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1af32c995a7b692a915bb7414d5f8e838450cf7c70414e763d8abcae7b51f28" + [[package]] name = "solana-program-memory" version = "2.1.9" @@ -2660,7 +2765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "247aba89bb78002423229ac0c78d954f82ac02f493dbdecacaf94627fa18bdd1" dependencies = [ "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.1.9", ] [[package]] @@ -2675,7 +2780,7 @@ version = "2.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23a1acbe8f1e2895659b06440f036cf3dd9949dbef0a123cefb3394a6d4192b2" dependencies = [ - "solana-program-error", + "solana-program-error 2.1.9", ] [[package]] @@ -2690,7 +2795,7 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "five8_const", + "five8_const 0.1.4", "getrandom 0.2.15", "js-sys", "num-traits", @@ -2699,9 +2804,9 @@ dependencies = [ "serde_derive", "solana-atomic-u64", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.1.9", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.1.9", "wasm-bindgen", ] @@ -2827,7 +2932,7 @@ checksum = "e7a3642a378c45f5d6110048ef88848c1835ad079affc4804b833f9692906f24" dependencies = [ "borsh 1.5.4", "libsecp256k1", - "solana-define-syscall", + "solana-define-syscall 2.1.9", "thiserror 1.0.69", ] @@ -2878,8 +2983,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "700bb300ed088d6c216fa32a2f383d290a9981b52620f7a39b37963a78d0fedb" dependencies = [ "sha2 0.10.8", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.1.9", + "solana-hash 2.1.9", +] + +[[package]] +name = "solana-sha256-hasher" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7dc3011ea4c0334aaaa7e7128cb390ecf546b28d412e9bf2064680f57f588f" +dependencies = [ + "sha2 0.10.8", + "solana-define-syscall 4.0.1", + "solana-hash 4.0.1", ] [[package]] @@ -2914,7 +3030,7 @@ checksum = "a25b7a24f410863eb9d2e69c19e412204c44cbaa338f45848a10111e0e100c94" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.1.9", "solana-sysvar-id", ] @@ -3058,8 +3174,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" dependencies = [ "bytemuck", - "solana-program-error", - "solana-sha256-hasher", + "solana-program-error 2.1.9", + "solana-sha256-hasher 2.1.9", "spl-discriminator-derive", ] @@ -3110,7 +3226,7 @@ dependencies = [ "solana-instruction", "solana-msg", "solana-program-entrypoint", - "solana-program-error", + "solana-program-error 2.1.9", "solana-pubkey", ] @@ -3127,7 +3243,7 @@ dependencies = [ "num-traits", "solana-decode-error", "solana-msg", - "solana-program-error", + "solana-program-error 2.1.9", "solana-program-option", "solana-pubkey", "solana-zk-sdk", @@ -3172,7 +3288,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.1.9", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -3327,7 +3443,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.1.9", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -3347,7 +3463,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.1.9", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -3370,7 +3486,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.1.9", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -3392,7 +3508,7 @@ dependencies = [ "solana-account-info", "solana-decode-error", "solana-msg", - "solana-program-error", + "solana-program-error 2.1.9", "spl-discriminator", "spl-pod", "thiserror 1.0.69", @@ -3411,8 +3527,12 @@ dependencies = [ "bytemuck", "fixed", "num_enum", + "pinocchio-system", "serde", - "solana-program", + "solana-account-view", + "solana-address", + "solana-instruction-view", + "solana-program-error 3.0.0", "spl-associated-token-account", "spl-token 4.0.2", "spl-token-2022 7.0.0", diff --git a/Cargo.toml b/Cargo.toml index a2ba99e..4f58907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,12 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.137" solana-clap-v3-utils = "^2.1" solana-cli-config = "^2.1" -solana-program = "^2.1" +solana-address = { version = "2.0", features = ["decode", "curve25519"] } +solana-account-view = "1.0" +solana-program-error = "3.0" +solana-instruction-view = { version = "1.0.0", features = ["cpi"] } +pinocchio-system = "0.4.0" +# solana-program = "^2.1" solana-sdk = "^2.1" spl-token = { features = ["no-entrypoint"], version = "^4" } spl-token-2022 = { features = ["no-entrypoint"], version = "^7" } diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 68c1fdc..d1ee7b1 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -19,7 +19,12 @@ bytemuck.workspace = true fixed.workspace = true num_enum.workspace = true serde.workspace = true -solana-program.workspace = true +# solana-program.workspace = true +solana-address.workspace = true +solana-account-view.workspace = true +solana-program-error.workspace = true +solana-instruction-view.workspace = true +pinocchio-system.workspace = true spl-token = { workspace = true, optional = true } spl-token-2022 = { workspace = true, optional = true } spl-associated-token-account = { workspace = true, optional = true } diff --git a/lib/src/account/close.rs b/lib/src/account/close.rs index af12b4b..023613d 100644 --- a/lib/src/account/close.rs +++ b/lib/src/account/close.rs @@ -1,20 +1,26 @@ -use solana_program::{account_info::AccountInfo, program_error::ProgramError, system_program}; +use solana_account_view::AccountView; +use solana_address::address; +use solana_program_error::ProgramError; +// use solana_program::{account_info::AccountInfo, program_error::ProgramError, system_program}; -pub trait CloseAccount<'info> { - fn close(&self, to: &AccountInfo<'info>) -> Result<(), ProgramError>; +pub trait CloseAccount { + fn close(&self, to: &AccountView) -> Result<(), ProgramError>; } -impl<'info> CloseAccount<'info> for AccountInfo<'info> { - fn close(&self, to: &AccountInfo<'info>) -> Result<(), ProgramError> { +impl CloseAccount for AccountView { + fn close(&self, to: &AccountView) -> Result<(), ProgramError> { // Return rent lamports. - **to.lamports.borrow_mut() += self.lamports(); - **self.lamports.borrow_mut() = 0; + to.set_lamports(to.lamports() + self.lamports()); + self.set_lamports(0); // Assign system program as the owner - self.assign(&system_program::ID); + unsafe { + // self.assign(&system_program::ID); + self.assign(&address!("11111111111111111111111111111111")); + } // Realloc data to zero. - self.realloc(0, true)?; + self.resize(0)?; Ok(()) } diff --git a/lib/src/account/deserialize.rs b/lib/src/account/deserialize.rs index 59f928d..e17ab07 100644 --- a/lib/src/account/deserialize.rs +++ b/lib/src/account/deserialize.rs @@ -1,6 +1,5 @@ use bytemuck::Pod; -use solana_program::program_error::ProgramError; - +use solana_program_error::ProgramError; pub trait Discriminator { fn discriminator() -> u8; } @@ -16,20 +15,18 @@ where { fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(solana_program::program_error::ProgramError::InvalidAccountData); + return Err(solana_program_error::ProgramError::InvalidAccountData); } - bytemuck::try_from_bytes::(&data[8..]).or(Err( - solana_program::program_error::ProgramError::InvalidAccountData, - )) + bytemuck::try_from_bytes::(&data[8..]) + .or(Err(solana_program_error::ProgramError::InvalidAccountData)) } fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(solana_program::program_error::ProgramError::InvalidAccountData); + return Err(solana_program_error::ProgramError::InvalidAccountData); } - bytemuck::try_from_bytes_mut::(&mut data[8..]).or(Err( - solana_program::program_error::ProgramError::InvalidAccountData, - )) + bytemuck::try_from_bytes_mut::(&mut data[8..]) + .or(Err(solana_program_error::ProgramError::InvalidAccountData)) } } @@ -50,13 +47,12 @@ where { fn try_header_from_bytes(data: &[u8]) -> Result<(&Self, &[u8]), ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(solana_program::program_error::ProgramError::InvalidAccountData); + return Err(solana_program_error::ProgramError::InvalidAccountData); } let (prefix, remainder) = data[8..].split_at(std::mem::size_of::()); Ok(( - bytemuck::try_from_bytes::(prefix).or(Err( - solana_program::program_error::ProgramError::InvalidAccountData, - ))?, + bytemuck::try_from_bytes::(prefix) + .or(Err(solana_program_error::ProgramError::InvalidAccountData))?, remainder, )) } @@ -64,9 +60,8 @@ where fn try_header_from_bytes_mut(data: &mut [u8]) -> Result<(&mut Self, &mut [u8]), ProgramError> { let (prefix, remainder) = data[8..].split_at_mut(std::mem::size_of::()); Ok(( - bytemuck::try_from_bytes_mut::(prefix).or(Err( - solana_program::program_error::ProgramError::InvalidAccountData, - ))?, + bytemuck::try_from_bytes_mut::(prefix) + .or(Err(solana_program_error::ProgramError::InvalidAccountData))?, remainder, )) } diff --git a/lib/src/account/lamports.rs b/lib/src/account/lamports.rs index a7e5a27..510b353 100644 --- a/lib/src/account/lamports.rs +++ b/lib/src/account/lamports.rs @@ -1,22 +1,28 @@ -use solana_program::{account_info::AccountInfo, program_error::ProgramError}; +use pinocchio_system::instructions::Transfer; +// use solana_program::{account_info::AccountInfo, program_error::ProgramError}; +use solana_account_view::AccountView; +use solana_program_error::ProgramError; -pub trait LamportTransfer<'a, 'info> { - fn send(&'a self, lamports: u64, to: &'a AccountInfo<'info>); - fn collect(&'a self, lamports: u64, from: &'a AccountInfo<'info>) -> Result<(), ProgramError>; +pub trait LamportTransfer { + fn send(&self, lamports: u64, to: &AccountView); + fn collect(&self, lamports: u64, from: &AccountView) -> Result<(), ProgramError>; } -impl<'a, 'info> LamportTransfer<'a, 'info> for AccountInfo<'info> { +impl LamportTransfer for AccountView { #[inline(always)] - fn send(&'a self, lamports: u64, to: &'a AccountInfo<'info>) { - **self.lamports.borrow_mut() -= lamports; - **to.lamports.borrow_mut() += lamports; + fn send(&self, lamports: u64, to: &AccountView) { + self.set_lamports(self.lamports() - lamports); + to.set_lamports(to.lamports() + lamports); } #[inline(always)] - fn collect(&'a self, lamports: u64, from: &'a AccountInfo<'info>) -> Result<(), ProgramError> { - solana_program::program::invoke( - &solana_program::system_instruction::transfer(from.key, self.key, lamports), - &[from.clone(), self.clone()], - ) + fn collect(&self, lamports: u64, from: &AccountView) -> Result<(), ProgramError> { + // Transfer { from, to, lamports }.invoke()?; + // solana_instruction_view::cpi::invoke::<2>(instruction, &[from, self]) + // solana_program::program::invoke( + // &solana_program::system_instruction::transfer(from.key, self.key, lamports), + // &[from.clone(), self.clone()], + // ) + Ok(()) } } diff --git a/lib/src/account/validation.rs b/lib/src/account/validation.rs index 75ec5c1..20a93a4 100644 --- a/lib/src/account/validation.rs +++ b/lib/src/account/validation.rs @@ -1,5 +1,8 @@ use bytemuck::Pod; -use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; +// use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; +use solana_account_view::AccountView; +use solana_address::Address; +use solana_program_error::ProgramError; use crate::trace; @@ -10,18 +13,18 @@ pub trait AccountInfoValidation { fn is_writable(&self) -> Result<&Self, ProgramError>; fn is_executable(&self) -> Result<&Self, ProgramError>; fn is_empty(&self) -> Result<&Self, ProgramError>; - fn is_type(&self, program_id: &Pubkey) -> Result<&Self, ProgramError>; - fn is_program(&self, program_id: &Pubkey) -> Result<&Self, ProgramError>; - fn is_sysvar(&self, sysvar_id: &Pubkey) -> Result<&Self, ProgramError>; - fn has_address(&self, address: &Pubkey) -> Result<&Self, ProgramError>; - fn has_owner(&self, program_id: &Pubkey) -> Result<&Self, ProgramError>; - fn has_seeds(&self, seeds: &[&[u8]], program_id: &Pubkey) -> Result<&Self, ProgramError>; + fn is_type(&self, program_id: &Address) -> Result<&Self, ProgramError>; + fn is_program(&self, program_id: &Address) -> Result<&Self, ProgramError>; + fn is_sysvar(&self, sysvar_id: &Address) -> Result<&Self, ProgramError>; + fn has_address(&self, address: &Address) -> Result<&Self, ProgramError>; + fn has_owner(&self, program_id: &Address) -> Result<&Self, ProgramError>; + fn has_seeds(&self, seeds: &[&[u8]], program_id: &Address) -> Result<&Self, ProgramError>; } -impl AccountInfoValidation for AccountInfo<'_> { +impl AccountInfoValidation for AccountView { #[track_caller] fn is_empty(&self) -> Result<&Self, ProgramError> { - if !self.data_is_empty() { + if !self.is_data_empty() { return Err(trace( "Account already initialized", ProgramError::AccountAlreadyInitialized, @@ -32,7 +35,7 @@ impl AccountInfoValidation for AccountInfo<'_> { #[track_caller] fn is_executable(&self) -> Result<&Self, ProgramError> { - if !self.executable { + if !self.executable() { return Err(trace( "Account is not executable", ProgramError::InvalidAccountData, @@ -42,13 +45,13 @@ impl AccountInfoValidation for AccountInfo<'_> { } #[track_caller] - fn is_program(&self, program_id: &Pubkey) -> Result<&Self, ProgramError> { + fn is_program(&self, program_id: &Address) -> Result<&Self, ProgramError> { self.has_address(program_id)?.is_executable() } #[track_caller] fn is_signer(&self) -> Result<&Self, ProgramError> { - if !self.is_signer { + if !self.is_signer() { return Err(trace( "Account is not a signer", ProgramError::MissingRequiredSignature, @@ -58,15 +61,15 @@ impl AccountInfoValidation for AccountInfo<'_> { } #[track_caller] - fn is_sysvar(&self, sysvar_id: &Pubkey) -> Result<&Self, ProgramError> { + fn is_sysvar(&self, sysvar_id: &Address) -> Result<&Self, ProgramError> { self.has_owner(&solana_program::sysvar::ID)? .has_address(sysvar_id) } #[track_caller] - fn is_type(&self, program_id: &Pubkey) -> Result<&Self, ProgramError> { + fn is_type(&self, program_id: &Address) -> Result<&Self, ProgramError> { self.has_owner(program_id)?; - if self.try_borrow_data()?[0].ne(&T::discriminator()) { + if unsafe { self.borrow_unchecked()[0] }.ne(&T::discriminator()) { return Err(trace( format!("Account is not of type {}", T::discriminator()).as_str(), ProgramError::InvalidAccountData, @@ -77,7 +80,7 @@ impl AccountInfoValidation for AccountInfo<'_> { #[track_caller] fn is_writable(&self) -> Result<&Self, ProgramError> { - if !self.is_writable { + if !self.is_writable() { return Err(trace( "Account is not writable", ProgramError::MissingRequiredSignature, @@ -87,10 +90,15 @@ impl AccountInfoValidation for AccountInfo<'_> { } #[track_caller] - fn has_address(&self, address: &Pubkey) -> Result<&Self, ProgramError> { - if self.key.ne(&address) { + fn has_address(&self, address: &Address) -> Result<&Self, ProgramError> { + if self.address().ne(address) { return Err(trace( - format!("Account has invalid address {} != {}", self.key, address).as_str(), + format!( + "Account has invalid address {} != {}", + self.address(), + address + ) + .as_str(), ProgramError::InvalidAccountData, )); } @@ -98,10 +106,15 @@ impl AccountInfoValidation for AccountInfo<'_> { } #[track_caller] - fn has_owner(&self, owner: &Pubkey) -> Result<&Self, ProgramError> { - if self.owner.ne(owner) { + fn has_owner(&self, owner: &Address) -> Result<&Self, ProgramError> { + if unsafe { self.owner() }.ne(owner) { return Err(trace( - format!("Account has invalid owner {} != {}", self.owner, owner).as_str(), + format!( + "Account has invalid owner {} != {}", + unsafe { *self.owner() }, + owner + ) + .as_str(), ProgramError::InvalidAccountOwner, )); } @@ -109,11 +122,11 @@ impl AccountInfoValidation for AccountInfo<'_> { } #[track_caller] - fn has_seeds(&self, seeds: &[&[u8]], program_id: &Pubkey) -> Result<&Self, ProgramError> { - let pda = Pubkey::find_program_address(seeds, program_id); - if self.key.ne(&pda.0) { + fn has_seeds(&self, seeds: &[&[u8]], program_id: &Address) -> Result<&Self, ProgramError> { + let pda = Address::find_program_address(seeds, program_id); + if self.address().ne(&pda.0) { return Err(trace( - format!("Account has invalid seeds {} != {}", self.key, pda.0).as_str(), + format!("Account has invalid seeds {} != {}", self.address(), pda.0).as_str(), ProgramError::InvalidSeeds, )); } @@ -126,18 +139,18 @@ impl AccountInfoValidation for AccountInfo<'_> { /// 2. Discriminator byte check /// 3. Checked bytemuck conversion of account data to &T or &mut T. pub trait AsAccount { - fn as_account(&self, program_id: &Pubkey) -> Result<&T, ProgramError> + fn as_account(&self, program_id: &Address) -> Result<&T, ProgramError> where T: AccountDeserialize + Discriminator + Pod; - fn as_account_mut(&self, program_id: &Pubkey) -> Result<&mut T, ProgramError> + fn as_account_mut(&self, program_id: &Address) -> Result<&mut T, ProgramError> where T: AccountDeserialize + Discriminator + Pod; } -impl AsAccount for AccountInfo<'_> { +impl AsAccount for AccountView { #[track_caller] - fn as_account(&self, program_id: &Pubkey) -> Result<&T, ProgramError> + fn as_account(&self, program_id: &Address) -> Result<&T, ProgramError> where T: AccountDeserialize + Discriminator + Pod, { @@ -146,7 +159,7 @@ impl AsAccount for AccountInfo<'_> { self.has_owner(program_id)?; // Validate account data length. - let data = self.try_borrow_data()?; + let data = self.borrow_unchecked(); let expected_len = 8 + std::mem::size_of::(); if data.len() != expected_len { return Err(trace( @@ -166,7 +179,7 @@ impl AsAccount for AccountInfo<'_> { } #[track_caller] - fn as_account_mut(&self, program_id: &Pubkey) -> Result<&mut T, ProgramError> + fn as_account_mut(&self, program_id: &Address) -> Result<&mut T, ProgramError> where T: AccountDeserialize + Discriminator + Pod, { @@ -175,7 +188,7 @@ impl AsAccount for AccountInfo<'_> { self.has_owner(program_id)?; // Validate account data length. - let mut data = self.try_borrow_mut_data()?; + let mut data = self.borrow_unchecked_mut(); let expected_len = 8 + std::mem::size_of::(); if data.len() != expected_len { return Err(trace( diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 31acc27..16be06a 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -15,15 +15,26 @@ pub use utils::*; pub use bytemuck::{Pod, Zeroable}; pub use num_enum::{IntoPrimitive, TryFromPrimitive}; -pub use solana_program::{ - account_info::AccountInfo, - clock::Clock, - declare_id, entrypoint, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - program_error::ProgramError, - pubkey::Pubkey, - system_program, sysvar, - sysvar::Sysvar, -}; +pub use solana_account_view::AccountView; +pub use solana_address::{address, Address}; +pub use solana_instruction_view::InstructionView; +pub use solana_program_error::{ProgramError, ProgramResult}; + +// use solana_clock::Clock; +// use solana_declare_id::declare_id; +// use solana_entrypoint::entrypoint; +// use solana_entrypoint::ProgramResult; +// use solana_instruction::Instruction; + +// pub use solana_program::{ +// account_info::AccountInfo, +// clock::Clock, +// declare_id, entrypoint, +// entrypoint::ProgramResult, +// instruction::{AccountMeta, Instruction}, +// program_error::ProgramError, +// pubkey::Pubkey, +// system_program, sysvar, +// sysvar::Sysvar, +// }; pub use thiserror::Error; diff --git a/lib/src/utils.rs b/lib/src/utils.rs index 98e3016..2d866cb 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -1,9 +1,10 @@ -use solana_program::{program_error::ProgramError, pubkey::Pubkey}; +use solana_address::Address; +use solana_program_error::ProgramError; /// Parses an instruction from the instruction data. pub fn parse_instruction<'a, T: std::convert::TryFrom>( - api_id: &'a Pubkey, - program_id: &'a Pubkey, + api_id: &Address, + program_id: &Address, data: &'a [u8], ) -> Result<(T, &'a [u8]), ProgramError> { // Validate the program id is valid. From 6800929f145b1893ff76e8afe365fa35fa9d01eb Mon Sep 17 00:00:00 2001 From: Perelyn <64838956+Perelyn-sama@users.noreply.github.com> Date: Wed, 10 Dec 2025 03:52:09 +0100 Subject: [PATCH 2/5] use pinocchio in cpi mod --- Cargo.lock | 61 +++++++++ Cargo.toml | 4 +- lib/Cargo.toml | 5 +- lib/src/account/close.rs | 1 - lib/src/account/cpi.rs | 231 ++++++++++++++------------------- lib/src/account/deserialize.rs | 28 ++-- lib/src/account/mod.rs | 8 +- lib/src/lib.rs | 34 ++--- 8 files changed, 205 insertions(+), 167 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c39ad0..de94f85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,6 +65,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -1844,6 +1853,26 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b971851087bc3699b001954ad02389d50c41405ece3548cbcafc88b3e20017a" +[[package]] +name = "pinocchio-log" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89f8ffd986174cefe59448295a004aaf70c3605f30de066f42d27b06188f267" +dependencies = [ + "pinocchio-log-macro", +] + +[[package]] +name = "pinocchio-log-macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edac6ac2c9c456b850d3e908b7f224a54623f6c5b75906b9e48a4e248fb332b" +dependencies = [ + "quote", + "regex", + "syn 1.0.109", +] + [[package]] name = "pinocchio-pubkey" version = "0.3.0" @@ -2044,6 +2073,35 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "rpassword" version = "7.3.1" @@ -3527,6 +3585,9 @@ dependencies = [ "bytemuck", "fixed", "num_enum", + "pinocchio", + "pinocchio-log", + "pinocchio-pubkey", "pinocchio-system", "serde", "solana-account-view", diff --git a/Cargo.toml b/Cargo.toml index 4f58907..10bdf43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,10 @@ solana-address = { version = "2.0", features = ["decode", "curve25519"] } solana-account-view = "1.0" solana-program-error = "3.0" solana-instruction-view = { version = "1.0.0", features = ["cpi"] } +pinocchio = "0.9.2" +pinocchio-log = "0.4.0" pinocchio-system = "0.4.0" +pinocchio-pubkey = "0.3.0" # solana-program = "^2.1" solana-sdk = "^2.1" spl-token = { features = ["no-entrypoint"], version = "^4" } @@ -43,4 +46,3 @@ thiserror = "1.0.57" tokio = "1.35" toml = "0.8.19" quote = "1.0" - diff --git a/lib/Cargo.toml b/lib/Cargo.toml index d1ee7b1..15ab018 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -24,9 +24,12 @@ solana-address.workspace = true solana-account-view.workspace = true solana-program-error.workspace = true solana-instruction-view.workspace = true -pinocchio-system.workspace = true spl-token = { workspace = true, optional = true } spl-token-2022 = { workspace = true, optional = true } spl-associated-token-account = { workspace = true, optional = true } thiserror.workspace = true +pinocchio.workspace = true +pinocchio-log.workspace = true +pinocchio-system.workspace = true +pinocchio-pubkey.workspace = true diff --git a/lib/src/account/close.rs b/lib/src/account/close.rs index 023613d..8eb225b 100644 --- a/lib/src/account/close.rs +++ b/lib/src/account/close.rs @@ -1,7 +1,6 @@ use solana_account_view::AccountView; use solana_address::address; use solana_program_error::ProgramError; -// use solana_program::{account_info::AccountInfo, program_error::ProgramError, system_program}; pub trait CloseAccount { fn close(&self, to: &AccountView) -> Result<(), ProgramError>; diff --git a/lib/src/account/cpi.rs b/lib/src/account/cpi.rs index 2ebfba2..d652c37 100644 --- a/lib/src/account/cpi.rs +++ b/lib/src/account/cpi.rs @@ -1,176 +1,148 @@ +#![allow(deprecated)] use bytemuck::Pod; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, instruction::Instruction, pubkey::Pubkey, - rent::Rent, sysvar::Sysvar, + +use pinocchio::sysvars::rent::{ + Rent, DEFAULT_BURN_PERCENT, DEFAULT_EXEMPTION_THRESHOLD, DEFAULT_LAMPORTS_PER_BYTE_YEAR, +}; +use pinocchio::{ + account_info::AccountInfo, + instruction::{Instruction, Seed, Signer}, + pubkey::Pubkey, + ProgramResult, }; -use crate::{CloseAccount, Discriminator}; +// TODO: remove with bump funcs? + +// use crate::{CloseAccount}; +use crate::Discriminator; /// Invokes a CPI with provided signer seeds and program id. #[inline(always)] -pub fn invoke_signed<'info>( +pub fn invoke_signed( instruction: &Instruction, - account_infos: &[AccountInfo<'info>], - program_id: &Pubkey, - seeds: &[&[u8]], + account_infos: &[&AccountInfo; ACCOUNTS], + seeds: &[Seed; N], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, program_id).1; - invoke_signed_with_bump(instruction, account_infos, seeds, bump) + invoke_signed_with_bump(instruction, account_infos, seeds) } /// Invokes a CPI with the provided signer seeds and bump. #[inline(always)] -pub fn invoke_signed_with_bump<'info>( +pub fn invoke_signed_with_bump( instruction: &Instruction, - account_infos: &[AccountInfo<'info>], - seeds: &[&[u8]], - bump: u8, + account_infos: &[&AccountInfo; ACCOUNTS], + seeds: &[Seed; N], ) -> ProgramResult { // Combine seeds - let bump: &[u8] = &[bump]; - let mut combined_seeds = Vec::with_capacity(seeds.len() + 1); - combined_seeds.extend_from_slice(seeds); - combined_seeds.push(bump); - let seeds = combined_seeds.as_slice(); + let signer_seeds = Signer::from(seeds); // Invoke CPI - solana_program::program::invoke_signed(instruction, account_infos, &[seeds]) + pinocchio::cpi::invoke_signed(instruction, account_infos, &[signer_seeds]) } /// Creates a new account. #[inline(always)] pub fn create_account<'a, 'info>( - from_pubkey: &'a AccountInfo<'info>, - to_pubkey: &'a AccountInfo<'info>, - system_program: &'a AccountInfo<'info>, + from: &'a AccountInfo, + to: &'a AccountInfo, space: usize, owner: &Pubkey, ) -> ProgramResult { - let lamports_required = (Rent::get()?).minimum_balance(space); - - solana_program::program::invoke( - &solana_program::system_instruction::create_account( - from_pubkey.key, - to_pubkey.key, - lamports_required, - space as u64, - owner, - ), - &[ - from_pubkey.clone(), - to_pubkey.clone(), - system_program.clone(), - ], - )?; + let rent = Rent { + lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE_YEAR, + exemption_threshold: DEFAULT_EXEMPTION_THRESHOLD, + burn_percent: DEFAULT_BURN_PERCENT, + }; + + let lamports_required = rent.minimum_balance(space); + + pinocchio_system::instructions::CreateAccount { + from, + to, + lamports: lamports_required, + space: space as u64, + owner, + } + .invoke()?; Ok(()) } /// Creates a new program account. #[inline(always)] -pub fn create_program_account<'a, 'info, T: Discriminator + Pod>( - target_account: &'a AccountInfo<'info>, - system_program: &'a AccountInfo<'info>, - payer: &'a AccountInfo<'info>, +pub fn create_program_account<'a, 'info, T: Discriminator + Pod, const N: usize>( + target_account: &'a AccountInfo, + payer: &'a AccountInfo, owner: &Pubkey, - seeds: &[&[u8]], + seeds: &[Seed; N], ) -> ProgramResult { - create_program_account_with_bump::( - target_account, - system_program, - payer, - owner, - seeds, - Pubkey::find_program_address(seeds, owner).1, - ) + create_program_account_with_bump::(target_account, payer, owner, seeds) } /// Creates a new program account with user-provided bump. #[inline(always)] -pub fn create_program_account_with_bump<'a, 'info, T: Discriminator + Pod>( - target_account: &'a AccountInfo<'info>, - system_program: &'a AccountInfo<'info>, - payer: &'a AccountInfo<'info>, +pub fn create_program_account_with_bump<'a, 'info, T: Discriminator + Pod, const N: usize>( + target_account: &'a AccountInfo, + payer: &'a AccountInfo, owner: &Pubkey, - seeds: &[&[u8]], - bump: u8, + seeds: &[Seed; N], ) -> ProgramResult { // Allocate space. allocate_account_with_bump( target_account, - system_program, payer, 8 + std::mem::size_of::(), owner, seeds, - bump, )?; // Set discriminator. - let mut data = target_account.data.borrow_mut(); - data[0] = T::discriminator(); + let mut data = target_account.try_borrow_mut_data()?; + data.copy_from_slice(&T::discriminator().to_le_bytes()); Ok(()) } /// Allocates space for a new program account. #[inline(always)] -pub fn allocate_account<'a, 'info>( - target_account: &'a AccountInfo<'info>, - system_program: &'a AccountInfo<'info>, - payer: &'a AccountInfo<'info>, +pub fn allocate_account<'a, 'info, const N: usize>( + target_account: &'a AccountInfo, + payer: &'a AccountInfo, space: usize, owner: &Pubkey, - seeds: &[&[u8]], + seeds: &[Seed; N], ) -> ProgramResult { - allocate_account_with_bump( - target_account, - system_program, - payer, - space, - owner, - seeds, - Pubkey::find_program_address(seeds, owner).1, - ) + allocate_account_with_bump(target_account, payer, space, owner, seeds) } /// Allocates space for a new program account with user-provided bump. #[inline(always)] -pub fn allocate_account_with_bump<'a, 'info>( - target_account: &'a AccountInfo<'info>, - system_program: &'a AccountInfo<'info>, - payer: &'a AccountInfo<'info>, +pub fn allocate_account_with_bump<'a, 'info, const N: usize>( + target_account: &'a AccountInfo, + payer: &'a AccountInfo, space: usize, owner: &Pubkey, - seeds: &[&[u8]], - bump: u8, + seeds: &[Seed; N], ) -> ProgramResult { - // Combine seeds - let bump: &[u8] = &[bump]; - let mut combined_seeds = Vec::with_capacity(seeds.len() + 1); - combined_seeds.extend_from_slice(seeds); - combined_seeds.push(bump); - let seeds = combined_seeds.as_slice(); + let signer_seeds = Signer::from(seeds); // Allocate space for account - let rent = Rent::get()?; + let rent = Rent { + lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE_YEAR, + exemption_threshold: DEFAULT_EXEMPTION_THRESHOLD, + burn_percent: DEFAULT_BURN_PERCENT, + }; if target_account.lamports().eq(&0) { // If balance is zero, create account - solana_program::program::invoke_signed( - &solana_program::system_instruction::create_account( - payer.key, - target_account.key, - rent.minimum_balance(space), - space as u64, - owner, - ), - &[ - payer.clone(), - target_account.clone(), - system_program.clone(), - ], - &[seeds], - )?; + + pinocchio_system::instructions::CreateAccount { + from: payer, + to: target_account, + lamports: rent.minimum_balance(space), + space: space as u64, + owner, + } + .invoke_signed(&[signer_seeds.clone()])?; } else { // Otherwise, if balance is nonzero: @@ -179,33 +151,28 @@ pub fn allocate_account_with_bump<'a, 'info>( .minimum_balance(space) .saturating_sub(target_account.lamports()); if rent_exempt_balance.gt(&0) { - solana_program::program::invoke( - &solana_program::system_instruction::transfer( - payer.key, - target_account.key, - rent_exempt_balance, - ), - &[ - payer.clone(), - target_account.clone(), - system_program.clone(), - ], - )?; + pinocchio_system::instructions::Transfer { + from: payer, + to: target_account, + lamports: rent_exempt_balance, + } + .invoke()?; } // 2) allocate space for the account - solana_program::program::invoke_signed( - &solana_program::system_instruction::allocate(target_account.key, space as u64), - &[target_account.clone(), system_program.clone()], - &[seeds], - )?; + + pinocchio_system::instructions::Allocate { + account: target_account, + space: space as u64, + } + .invoke_signed(&[signer_seeds.clone()])?; // 3) assign our program as the owner - solana_program::program::invoke_signed( - &solana_program::system_instruction::assign(target_account.key, owner), - &[target_account.clone(), system_program.clone()], - &[seeds], - )?; + pinocchio_system::instructions::Assign { + account: target_account, + owner, + } + .invoke_signed(&[signer_seeds])?; } Ok(()) @@ -213,9 +180,11 @@ pub fn allocate_account_with_bump<'a, 'info>( /// Closes an account and returns the remaining rent lamports to the provided recipient. #[inline(always)] -pub fn close_account<'info>( - account_info: &AccountInfo<'info>, - recipient: &AccountInfo<'info>, -) -> ProgramResult { - account_info.close(recipient) +pub fn close_account(account_info: &AccountInfo, recipient: &AccountInfo) -> ProgramResult { + let lamports = account_info.lamports(); + + *account_info.try_borrow_mut_lamports()? -= lamports; + *recipient.try_borrow_mut_lamports()? += lamports; + + account_info.close() } diff --git a/lib/src/account/deserialize.rs b/lib/src/account/deserialize.rs index e17ab07..e8e31fe 100644 --- a/lib/src/account/deserialize.rs +++ b/lib/src/account/deserialize.rs @@ -1,5 +1,5 @@ use bytemuck::Pod; -use solana_program_error::ProgramError; +use pinocchio::program_error::ProgramError; pub trait Discriminator { fn discriminator() -> u8; } @@ -15,18 +15,20 @@ where { fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(solana_program_error::ProgramError::InvalidAccountData); + return Err(pinocchio::program_error::ProgramError::InvalidAccountData); } - bytemuck::try_from_bytes::(&data[8..]) - .or(Err(solana_program_error::ProgramError::InvalidAccountData)) + bytemuck::try_from_bytes::(&data[8..]).or(Err( + pinocchio::program_error::ProgramError::InvalidAccountData, + )) } fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(solana_program_error::ProgramError::InvalidAccountData); + return Err(pinocchio::program_error::ProgramError::InvalidAccountData); } - bytemuck::try_from_bytes_mut::(&mut data[8..]) - .or(Err(solana_program_error::ProgramError::InvalidAccountData)) + bytemuck::try_from_bytes_mut::(&mut data[8..]).or(Err( + pinocchio::program_error::ProgramError::InvalidAccountData, + )) } } @@ -47,12 +49,13 @@ where { fn try_header_from_bytes(data: &[u8]) -> Result<(&Self, &[u8]), ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(solana_program_error::ProgramError::InvalidAccountData); + return Err(pinocchio::program_error::ProgramError::InvalidAccountData); } let (prefix, remainder) = data[8..].split_at(std::mem::size_of::()); Ok(( - bytemuck::try_from_bytes::(prefix) - .or(Err(solana_program_error::ProgramError::InvalidAccountData))?, + bytemuck::try_from_bytes::(prefix).or(Err( + pinocchio::program_error::ProgramError::InvalidAccountData, + ))?, remainder, )) } @@ -60,8 +63,9 @@ where fn try_header_from_bytes_mut(data: &mut [u8]) -> Result<(&mut Self, &mut [u8]), ProgramError> { let (prefix, remainder) = data[8..].split_at_mut(std::mem::size_of::()); Ok(( - bytemuck::try_from_bytes_mut::(prefix) - .or(Err(solana_program_error::ProgramError::InvalidAccountData))?, + bytemuck::try_from_bytes_mut::(prefix).or(Err( + pinocchio::program_error::ProgramError::InvalidAccountData, + ))?, remainder, )) } diff --git a/lib/src/account/mod.rs b/lib/src/account/mod.rs index acde9c3..9f0ac7c 100644 --- a/lib/src/account/mod.rs +++ b/lib/src/account/mod.rs @@ -1,11 +1,11 @@ mod close; mod cpi; mod deserialize; -mod lamports; -mod validation; +// mod lamports; +// mod validation; pub use close::*; pub use cpi::*; pub use deserialize::*; -pub use lamports::*; -pub use validation::*; +// pub use lamports::*; +// pub use validation::*; diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 16be06a..891ffa0 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1,24 +1,24 @@ mod account; -mod log; -pub mod macros; -mod numeric; -#[cfg(feature = "spl")] -mod spl; -mod utils; +// mod log; +// pub mod macros; +// mod numeric; +// #[cfg(feature = "spl")] +// mod spl; +// mod utils; pub use account::*; -pub use log::*; -pub use numeric::*; -#[cfg(feature = "spl")] -pub use spl::*; -pub use utils::*; +// pub use log::*; +// pub use numeric::*; +// #[cfg(feature = "spl")] +// pub use spl::*; +// pub use utils::*; -pub use bytemuck::{Pod, Zeroable}; -pub use num_enum::{IntoPrimitive, TryFromPrimitive}; -pub use solana_account_view::AccountView; -pub use solana_address::{address, Address}; -pub use solana_instruction_view::InstructionView; -pub use solana_program_error::{ProgramError, ProgramResult}; +// pub use bytemuck::{Pod, Zeroable}; +// pub use num_enum::{IntoPrimitive, TryFromPrimitive}; +// pub use solana_account_view::AccountView; +// pub use solana_address::{address, Address}; +// pub use solana_instruction_view::InstructionView; +// pub use solana_program_error::{ProgramError, ProgramResult}; // use solana_clock::Clock; // use solana_declare_id::declare_id; From 349e2f50decd3a081e9cce312a2d6705fe2ab108 Mon Sep 17 00:00:00 2001 From: Perelyn <64838956+Perelyn-sama@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:47:19 +0100 Subject: [PATCH 3/5] refactor account/cpi and spl/cpi to use pinocchio v0.10 --- Cargo.lock | 72 +- Cargo.toml | 9 +- lib/Cargo.toml | 3 + lib/src/account/cpi.rs | 148 ++-- lib/src/account/deserialize.rs | 26 +- lib/src/lib.rs | 8 +- lib/src/spl/cpi.rs | 1391 +++++++++----------------------- lib/src/spl/mod.rs | 12 +- 8 files changed, 572 insertions(+), 1097 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de94f85..9c66b06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1853,20 +1853,45 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b971851087bc3699b001954ad02389d50c41405ece3548cbcafc88b3e20017a" +[[package]] +name = "pinocchio" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfad955b2fe8f736e1ea276ebb31820d778ee69c1161146054e9b31be2e73326" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-define-syscall 4.0.1", + "solana-instruction-view", + "solana-program-error 3.0.0", +] + +[[package]] +name = "pinocchio-associated-token-account" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd92823a97fb327d7509dfd7cbfa3ead56e9fc0e131972bc0e28ab7036be31a" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-instruction-view", + "solana-program-error 3.0.0", +] + [[package]] name = "pinocchio-log" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89f8ffd986174cefe59448295a004aaf70c3605f30de066f42d27b06188f267" +checksum = "cd11022408f312e6179ece321c1f7dc0d1b2aa7765fddd39b2a7378d65a899e8" dependencies = [ "pinocchio-log-macro", ] [[package]] name = "pinocchio-log-macro" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6edac6ac2c9c456b850d3e908b7f224a54623f6c5b75906b9e48a4e248fb332b" +checksum = "69fb52edb3c5736b044cc462b0957b9767d0f574d138f4e2761438c498a4b467" dependencies = [ "quote", "regex", @@ -1880,18 +1905,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0225638cadcbebae8932cb7f49cb5da7c15c21beb19f048f05a5ca7d93f065" dependencies = [ "five8_const 0.1.4", - "pinocchio", + "pinocchio 0.9.2", "sha2-const-stable", ] [[package]] name = "pinocchio-system" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2a6dad40b5e75d1486f021619c4bd504c34c1362c9b94ed7fa525b1cc63cc" +checksum = "24044a0815753862b558e179e78f03f7344cb755de48617a09d7d23b50883b6c" dependencies = [ - "pinocchio", - "pinocchio-pubkey", + "pinocchio 0.10.1", + "solana-address", +] + +[[package]] +name = "pinocchio-token" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "febf3bbe37f4e2723b9b41a1768c6542a1ae1b1d7bcac27f892f30cabcf70ec4" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-instruction-view", + "solana-program-error 3.0.0", +] + +[[package]] +name = "pinocchio-token-2022" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbe4f1997ce2443f99333d8ae2ee1075f9c94ed13ff941178663ae3601ad99ad" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-instruction-view", + "solana-program-error 3.0.0", ] [[package]] @@ -3585,10 +3634,13 @@ dependencies = [ "bytemuck", "fixed", "num_enum", - "pinocchio", + "pinocchio 0.10.1", + "pinocchio-associated-token-account", "pinocchio-log", "pinocchio-pubkey", "pinocchio-system", + "pinocchio-token", + "pinocchio-token-2022", "serde", "solana-account-view", "solana-address", diff --git a/Cargo.toml b/Cargo.toml index 10bdf43..d3e776b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,10 +33,13 @@ solana-address = { version = "2.0", features = ["decode", "curve25519"] } solana-account-view = "1.0" solana-program-error = "3.0" solana-instruction-view = { version = "1.0.0", features = ["cpi"] } -pinocchio = "0.9.2" -pinocchio-log = "0.4.0" -pinocchio-system = "0.4.0" +pinocchio = { version = "0.10.1", features = ["cpi"] } +pinocchio-log = "0.5.1" +pinocchio-system = "0.5.0" pinocchio-pubkey = "0.3.0" +pinocchio-associated-token-account = "0.3.0" +pinocchio-token-2022 = "0.2.0" +pinocchio-token = "0.5.0" # solana-program = "^2.1" solana-sdk = "^2.1" spl-token = { features = ["no-entrypoint"], version = "^4" } diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 15ab018..8f18662 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -33,3 +33,6 @@ pinocchio.workspace = true pinocchio-log.workspace = true pinocchio-system.workspace = true pinocchio-pubkey.workspace = true +pinocchio-associated-token-account.workspace = true +pinocchio-token.workspace = true +pinocchio-token-2022.workspace = true diff --git a/lib/src/account/cpi.rs b/lib/src/account/cpi.rs index d652c37..bca2a56 100644 --- a/lib/src/account/cpi.rs +++ b/lib/src/account/cpi.rs @@ -1,60 +1,89 @@ -#![allow(deprecated)] use bytemuck::Pod; -use pinocchio::sysvars::rent::{ - Rent, DEFAULT_BURN_PERCENT, DEFAULT_EXEMPTION_THRESHOLD, DEFAULT_LAMPORTS_PER_BYTE_YEAR, -}; +use pinocchio::cpi; +use pinocchio::sysvars::rent::Rent; +use pinocchio::sysvars::Sysvar; use pinocchio::{ - account_info::AccountInfo, - instruction::{Instruction, Seed, Signer}, - pubkey::Pubkey, - ProgramResult, + cpi::{Seed, Signer}, + instruction::InstructionView, + AccountView, Address, ProgramResult, }; -// TODO: remove with bump funcs? - // use crate::{CloseAccount}; use crate::Discriminator; /// Invokes a CPI with provided signer seeds and program id. #[inline(always)] pub fn invoke_signed( - instruction: &Instruction, - account_infos: &[&AccountInfo; ACCOUNTS], + instruction: &InstructionView, + account_views: &[&AccountView; ACCOUNTS], seeds: &[Seed; N], ) -> ProgramResult { - invoke_signed_with_bump(instruction, account_infos, seeds) + let signers_seeds = Signer::from(seeds); + + cpi::invoke_signed(instruction, account_views, &[signers_seeds]) } -/// Invokes a CPI with the provided signer seeds and bump. -#[inline(always)] -pub fn invoke_signed_with_bump( - instruction: &Instruction, - account_infos: &[&AccountInfo; ACCOUNTS], - seeds: &[Seed; N], -) -> ProgramResult { - // Combine seeds - let signer_seeds = Signer::from(seeds); +// #[inline(always)] +// pub fn invoke_signed_with_bump( +// instruction: &Instruction, +// account_infos: &[&AccountInfo; ACCOUNTS], +// seeds: &[&[u8]; N], +// bump: &[u8], +// ) -> ProgramResult { +// // Create a buffer large enough for any reasonable PDA (max 16 seeds) +// let mut all_seeds: [&[u8]; 16] = [&[]; 16]; - // Invoke CPI - pinocchio::cpi::invoke_signed(instruction, account_infos, &[signer_seeds]) -} +// // Copy input seeds +// all_seeds[..N].copy_from_slice(seeds); + +// // Append bump +// all_seeds[N] = bump; + +// // Use only the slice we need (N + 1 elements) +// pinocchio::cpi::invoke_signed(instruction, account_infos, &[&all_seeds[..N + 1]]) +// } + +/// Invokes a CPI with the provided signer seeds and bump. +// #[inline(always)] +// pub fn invoke_signed_with_bump( +// instruction: &Instruction, +// account_infos: &[&AccountInfo; ACCOUNTS], +// seeds: &[&[u8]], +// bump: &[u8], +// ) -> ProgramResult { +// let len = seeds.len(); +// let mut res; + +// for (i, e) in seeds.iter().enumerate() { +// res = [ +// Seed::from(seeds[i]), +// Seed::from(seeds[i + 1]), +// Seed::from(seeds[i + 2]), +// ]; +// } + +// // if seeds.len == 3 +// // + +// // Combine seeds +// let signer_seeds = Signer::from(seeds); + +// // Invoke CPI +// pinocchio::cpi::invoke_signed(instruction, account_infos, &[signer_seeds]) +// } /// Creates a new account. #[inline(always)] pub fn create_account<'a, 'info>( - from: &'a AccountInfo, - to: &'a AccountInfo, + from: &'a AccountView, + to: &'a AccountView, space: usize, - owner: &Pubkey, + owner: &Address, ) -> ProgramResult { - let rent = Rent { - lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE_YEAR, - exemption_threshold: DEFAULT_EXEMPTION_THRESHOLD, - burn_percent: DEFAULT_BURN_PERCENT, - }; + let rent = Rent::get()?; - let lamports_required = rent.minimum_balance(space); + let lamports_required = rent.try_minimum_balance(space)?; pinocchio_system::instructions::CreateAccount { from, @@ -68,12 +97,20 @@ pub fn create_account<'a, 'info>( Ok(()) } +// fn append(arr: [T; N], elem: T) -> [T; M] { + +// let mut result = [elem; M]; +// result[..N].copy_from_slice(&arr); +// result[N] = elem; +// result +// } + /// Creates a new program account. #[inline(always)] pub fn create_program_account<'a, 'info, T: Discriminator + Pod, const N: usize>( - target_account: &'a AccountInfo, - payer: &'a AccountInfo, - owner: &Pubkey, + target_account: &'a AccountView, + payer: &'a AccountView, + owner: &Address, seeds: &[Seed; N], ) -> ProgramResult { create_program_account_with_bump::(target_account, payer, owner, seeds) @@ -82,9 +119,9 @@ pub fn create_program_account<'a, 'info, T: Discriminator + Pod, const N: usize> /// Creates a new program account with user-provided bump. #[inline(always)] pub fn create_program_account_with_bump<'a, 'info, T: Discriminator + Pod, const N: usize>( - target_account: &'a AccountInfo, - payer: &'a AccountInfo, - owner: &Pubkey, + target_account: &'a AccountView, + payer: &'a AccountView, + owner: &Address, seeds: &[Seed; N], ) -> ProgramResult { // Allocate space. @@ -97,7 +134,7 @@ pub fn create_program_account_with_bump<'a, 'info, T: Discriminator + Pod, const )?; // Set discriminator. - let mut data = target_account.try_borrow_mut_data()?; + let mut data = target_account.try_borrow_mut()?; data.copy_from_slice(&T::discriminator().to_le_bytes()); Ok(()) @@ -106,10 +143,10 @@ pub fn create_program_account_with_bump<'a, 'info, T: Discriminator + Pod, const /// Allocates space for a new program account. #[inline(always)] pub fn allocate_account<'a, 'info, const N: usize>( - target_account: &'a AccountInfo, - payer: &'a AccountInfo, + target_account: &'a AccountView, + payer: &'a AccountView, space: usize, - owner: &Pubkey, + owner: &Address, seeds: &[Seed; N], ) -> ProgramResult { allocate_account_with_bump(target_account, payer, space, owner, seeds) @@ -118,27 +155,24 @@ pub fn allocate_account<'a, 'info, const N: usize>( /// Allocates space for a new program account with user-provided bump. #[inline(always)] pub fn allocate_account_with_bump<'a, 'info, const N: usize>( - target_account: &'a AccountInfo, - payer: &'a AccountInfo, + target_account: &'a AccountView, + payer: &'a AccountView, space: usize, - owner: &Pubkey, + owner: &Address, seeds: &[Seed; N], ) -> ProgramResult { let signer_seeds = Signer::from(seeds); // Allocate space for account - let rent = Rent { - lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE_YEAR, - exemption_threshold: DEFAULT_EXEMPTION_THRESHOLD, - burn_percent: DEFAULT_BURN_PERCENT, - }; + let rent = Rent::get()?; + if target_account.lamports().eq(&0) { // If balance is zero, create account pinocchio_system::instructions::CreateAccount { from: payer, to: target_account, - lamports: rent.minimum_balance(space), + lamports: rent.try_minimum_balance(space)?, space: space as u64, owner, } @@ -148,7 +182,7 @@ pub fn allocate_account_with_bump<'a, 'info, const N: usize>( // 1) transfer sufficient lamports for rent exemption let rent_exempt_balance = rent - .minimum_balance(space) + .try_minimum_balance(space)? .saturating_sub(target_account.lamports()); if rent_exempt_balance.gt(&0) { pinocchio_system::instructions::Transfer { @@ -180,11 +214,11 @@ pub fn allocate_account_with_bump<'a, 'info, const N: usize>( /// Closes an account and returns the remaining rent lamports to the provided recipient. #[inline(always)] -pub fn close_account(account_info: &AccountInfo, recipient: &AccountInfo) -> ProgramResult { +pub fn close_account(account_info: &AccountView, recipient: &AccountView) -> ProgramResult { let lamports = account_info.lamports(); - *account_info.try_borrow_mut_lamports()? -= lamports; - *recipient.try_borrow_mut_lamports()? += lamports; + account_info.set_lamports(lamports - lamports); + recipient.set_lamports(recipient.lamports() + lamports); account_info.close() } diff --git a/lib/src/account/deserialize.rs b/lib/src/account/deserialize.rs index e8e31fe..511213a 100644 --- a/lib/src/account/deserialize.rs +++ b/lib/src/account/deserialize.rs @@ -1,5 +1,5 @@ use bytemuck::Pod; -use pinocchio::program_error::ProgramError; +use pinocchio::error::ProgramError; pub trait Discriminator { fn discriminator() -> u8; } @@ -15,20 +15,17 @@ where { fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(pinocchio::program_error::ProgramError::InvalidAccountData); + return Err(ProgramError::InvalidAccountData); } - bytemuck::try_from_bytes::(&data[8..]).or(Err( - pinocchio::program_error::ProgramError::InvalidAccountData, - )) + bytemuck::try_from_bytes::(&data[8..]).or(Err(ProgramError::InvalidAccountData)) } fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(pinocchio::program_error::ProgramError::InvalidAccountData); + return Err(ProgramError::InvalidAccountData); } - bytemuck::try_from_bytes_mut::(&mut data[8..]).or(Err( - pinocchio::program_error::ProgramError::InvalidAccountData, - )) + bytemuck::try_from_bytes_mut::(&mut data[8..]) + .or(Err(ProgramError::InvalidAccountData)) } } @@ -49,13 +46,11 @@ where { fn try_header_from_bytes(data: &[u8]) -> Result<(&Self, &[u8]), ProgramError> { if Self::discriminator().ne(&data[0]) { - return Err(pinocchio::program_error::ProgramError::InvalidAccountData); + return Err(ProgramError::InvalidAccountData); } let (prefix, remainder) = data[8..].split_at(std::mem::size_of::()); Ok(( - bytemuck::try_from_bytes::(prefix).or(Err( - pinocchio::program_error::ProgramError::InvalidAccountData, - ))?, + bytemuck::try_from_bytes::(prefix).or(Err(ProgramError::InvalidAccountData))?, remainder, )) } @@ -63,9 +58,8 @@ where fn try_header_from_bytes_mut(data: &mut [u8]) -> Result<(&mut Self, &mut [u8]), ProgramError> { let (prefix, remainder) = data[8..].split_at_mut(std::mem::size_of::()); Ok(( - bytemuck::try_from_bytes_mut::(prefix).or(Err( - pinocchio::program_error::ProgramError::InvalidAccountData, - ))?, + bytemuck::try_from_bytes_mut::(prefix) + .or(Err(ProgramError::InvalidAccountData))?, remainder, )) } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 891ffa0..7994408 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -2,15 +2,15 @@ mod account; // mod log; // pub mod macros; // mod numeric; -// #[cfg(feature = "spl")] -// mod spl; +#[cfg(feature = "spl")] +mod spl; // mod utils; pub use account::*; // pub use log::*; // pub use numeric::*; -// #[cfg(feature = "spl")] -// pub use spl::*; +#[cfg(feature = "spl")] +pub use spl::*; // pub use utils::*; // pub use bytemuck::{Pod, Zeroable}; diff --git a/lib/src/spl/cpi.rs b/lib/src/spl/cpi.rs index d753f83..97b6adb 100644 --- a/lib/src/spl/cpi.rs +++ b/lib/src/spl/cpi.rs @@ -1,1164 +1,553 @@ -use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey}; - -use crate::account::invoke_signed_with_bump; - -#[inline(always)] -pub fn create_associated_token_account<'info>( - funder_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - system_program: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - associated_token_program: &AccountInfo<'info>, -) -> ProgramResult { - solana_program::program::invoke( - &spl_associated_token_account::instruction::create_associated_token_account( - funder_info.key, - owner_info.key, - mint_info.key, - &token_program.key, - ), - &[ - funder_info.clone(), - token_account_info.clone(), - owner_info.clone(), - mint_info.clone(), - system_program.clone(), - token_program.clone(), - associated_token_program.clone(), - ], - ) -} - -#[inline(always)] -pub fn close_token_account<'info>( - account_info: &AccountInfo<'info>, - destination_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, -) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::close_account( - &token_program.key, - &account_info.key, - &destination_info.key, - &owner_info.key, - &[&owner_info.key], - )?, - &[ - token_program.clone(), - account_info.clone(), - destination_info.clone(), - owner_info.clone(), - ], - ) -} - -#[inline(always)] -pub fn close_token_account_signed<'info>( - account_info: &AccountInfo<'info>, - destination_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], -) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, owner_info.owner).1; - close_token_account_signed_with_bump( - account_info, - destination_info, - owner_info, +use pinocchio::{ + cpi::{Seed, Signer}, + AccountView, Address, ProgramResult, +}; + +// use crate::account::invoke_signed_with_bump; + +#[inline(always)] +pub fn create_associated_token_account( + funder_info: &AccountView, + owner_info: &AccountView, + token_account_info: &AccountView, + mint_info: &AccountView, + system_program: &AccountView, + token_program: &AccountView, +) -> ProgramResult { + pinocchio_associated_token_account::instructions::Create { + funding_account: funder_info, + account: token_account_info, + wallet: owner_info, + mint: mint_info, + system_program, token_program, - seeds, - bump, - ) + } + .invoke() } +// TODO: why is this using token 2022? #[inline(always)] -pub fn close_token_account_signed_with_bump<'info>( - account_info: &AccountInfo<'info>, - destination_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], - bump: u8, +pub fn close_token_account( + account_info: &AccountView, + destination_info: &AccountView, + owner_info: &AccountView, + token_program: &Address, ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::close_account( - &token_program.key, - &account_info.key, - &destination_info.key, - &owner_info.key, - &[&owner_info.key], - )?, - &[ - token_program.clone(), - account_info.clone(), - destination_info.clone(), - owner_info.clone(), - ], - seeds, - bump, - ) + pinocchio_token_2022::instructions::CloseAccount { + account: account_info, + destination: destination_info, + authority: owner_info, + token_program: token_program, + } + .invoke() } #[inline(always)] -pub fn transfer<'info>( - authority_info: &AccountInfo<'info>, - from_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, +pub fn close_token_account_signed( + account_info: &AccountView, + destination_info: &AccountView, + owner_info: &AccountView, + token_program: &Address, + seeds: &[Seed; N], ) -> ProgramResult { - #[allow(deprecated)] - solana_program::program::invoke( - &spl_token_2022::instruction::transfer( - &token_program.key, - from_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - from_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn transfer_signed<'info>( - authority_info: &AccountInfo<'info>, - from_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, - seeds: &[&[u8]], -) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - transfer_signed_with_bump( - authority_info, - from_info, - to_info, - token_program, - amount, - seeds, - bump, - ) + pinocchio_token_2022::instructions::CloseAccount { + account: account_info, + destination: destination_info, + authority: owner_info, + token_program: token_program, + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn transfer_signed_with_bump<'info>( - authority_info: &AccountInfo<'info>, - from_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn transfer( + authority_info: &AccountView, + from_info: &AccountView, + to_info: &AccountView, + token_program: &Address, amount: u64, - seeds: &[&[u8]], - bump: u8, ) -> ProgramResult { - #[allow(deprecated)] - invoke_signed_with_bump( - &spl_token_2022::instruction::transfer( - &token_program.key, - from_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - from_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - seeds, - bump, - ) + pinocchio_token_2022::instructions::Transfer { + from: from_info, + to: to_info, + authority: authority_info, + amount: amount, + token_program: token_program, + } + .invoke() } #[inline(always)] -pub fn transfer_checked<'info>( - authority_info: &AccountInfo<'info>, - from_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn transfer_signed( + authority_info: &AccountView, + from_info: &AccountView, + to_info: &AccountView, + token_program: &Address, amount: u64, - decimals: u8, + seeds: &[Seed; N], ) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::transfer_checked( - &token_program.key, - from_info.key, - mint_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - decimals, - )?, - &[ - token_program.clone(), - from_info.clone(), - mint_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - ) + let signer_seeds = Signer::from(seeds); + + pinocchio_token_2022::instructions::Transfer { + from: from_info, + to: to_info, + authority: authority_info, + amount: amount, + token_program: token_program, + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn transfer_checked_signed<'info>( - authority_info: &AccountInfo<'info>, - from_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn transfer_checked( + authority_info: &AccountView, + from_info: &AccountView, + mint_info: &AccountView, + to_info: &AccountView, + token_program: &Address, amount: u64, decimals: u8, - seeds: &[&[u8]], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - transfer_checked_signed_with_bump( - authority_info, - from_info, - mint_info, - to_info, - token_program, + pinocchio_token_2022::instructions::TransferChecked { + from: from_info, + mint: mint_info, + to: to_info, + token_program: token_program, + authority: authority_info, amount, decimals, - seeds, - bump, - ) + } + .invoke() } #[inline(always)] -pub fn transfer_checked_signed_with_bump<'info>( - authority_info: &AccountInfo<'info>, - from_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn transfer_checked_signed( + authority_info: &AccountView, + from_info: &AccountView, + mint_info: &AccountView, + to_info: &AccountView, + token_program: &Address, amount: u64, decimals: u8, - seeds: &[&[u8]], - bump: u8, + seeds: &[Seed; N], ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::transfer_checked( - &token_program.key, - from_info.key, - mint_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - decimals, - )?, - &[ - token_program.clone(), - from_info.clone(), - mint_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - seeds, - bump, - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn mint_to_signed<'info>( - mint_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, - seeds: &[&[u8]], -) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - mint_to_signed_with_bump( - mint_info, - to_info, - authority_info, - token_program, + pinocchio_token_2022::instructions::TransferChecked { + from: from_info, + mint: mint_info, + to: to_info, + token_program: token_program, + authority: authority_info, amount, - seeds, - bump, - ) + decimals, + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn mint_to_signed_with_bump<'info>( - mint_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn mint_to_signed( + mint_info: &AccountView, + to_info: &AccountView, + authority_info: &AccountView, amount: u64, - seeds: &[&[u8]], - bump: u8, + seeds: &[Seed; N], ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::mint_to( - &token_program.key, - mint_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - mint_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - seeds, - bump, - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn mint_to_checked_signed<'info>( - mint_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, - decimals: u8, - seeds: &[&[u8]], -) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - mint_to_checked_signed_with_bump( - mint_info, - to_info, - authority_info, - token_program, + pinocchio_token::instructions::MintTo { + mint: mint_info, + account: to_info, + mint_authority: authority_info, amount, - decimals, - seeds, - bump, - ) + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn mint_to_checked_signed_with_bump<'info>( - mint_info: &AccountInfo<'info>, - to_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn mint_to_checked_signed( + mint_info: &AccountView, + to_info: &AccountView, + authority_info: &AccountView, amount: u64, decimals: u8, - seeds: &[&[u8]], - bump: u8, + seeds: &[Seed; N], ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::mint_to_checked( - &token_program.key, - mint_info.key, - to_info.key, - authority_info.key, - &[authority_info.key], - amount, - decimals, - )?, - &[ - token_program.clone(), - mint_info.clone(), - to_info.clone(), - authority_info.clone(), - ], - seeds, - bump, - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn burn<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, -) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::burn( - &token_program.key, - token_account_info.key, - mint_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - token_account_info.clone(), - mint_info.clone(), - authority_info.clone(), - ], - ) + pinocchio_token::instructions::MintToChecked { + mint: mint_info, + account: to_info, + mint_authority: authority_info, + amount, + decimals, + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn burn_signed<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn burn( + token_account_info: &AccountView, + mint_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, amount: u64, - seeds: &[&[u8]], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - burn_signed_with_bump( - token_account_info, - mint_info, - authority_info, - token_program, + pinocchio_token_2022::instructions::Burn { + account: token_account_info, + mint: mint_info, + authority: authority_info, amount, - seeds, - bump, - ) + token_program, + } + .invoke() } #[inline(always)] -pub fn burn_signed_with_bump<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn burn_signed( + token_account_info: &AccountView, + mint_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, amount: u64, - seeds: &[&[u8]], - bump: u8, + seeds: &[Seed; N], ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::burn( - &token_program.key, - token_account_info.key, - mint_info.key, - authority_info.key, - &[authority_info.key], - amount, - )?, - &[ - token_program.clone(), - token_account_info.clone(), - mint_info.clone(), - authority_info.clone(), - ], - seeds, - bump, - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn burn_checked<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, - decimals: u8, -) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::burn_checked( - &token_program.key, - token_account_info.key, - mint_info.key, - authority_info.key, - &[authority_info.key], - amount, - decimals, - )?, - &[ - token_program.clone(), - token_account_info.clone(), - mint_info.clone(), - authority_info.clone(), - ], - ) + pinocchio_token_2022::instructions::Burn { + account: token_account_info, + mint: mint_info, + authority: authority_info, + amount, + token_program, + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn burn_checked_signed<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn burn_checked( + token_account_info: &AccountView, + mint_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, amount: u64, decimals: u8, - seeds: &[&[u8]], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - burn_checked_signed_with_bump( - token_account_info, - mint_info, - authority_info, - token_program, + pinocchio_token_2022::instructions::BurnChecked { + account: token_account_info, + mint: mint_info, + authority: authority_info, amount, decimals, - seeds, - bump, - ) + token_program, + } + .invoke() } #[inline(always)] -pub fn burn_checked_signed_with_bump<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn burn_checked_signed( + token_account_info: &AccountView, + mint_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, amount: u64, decimals: u8, - seeds: &[&[u8]], - bump: u8, + seeds: &[Seed; N], ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::burn_checked( - &token_program.key, - token_account_info.key, - mint_info.key, - authority_info.key, - &[authority_info.key], - amount, - decimals, - )?, - &[ - token_program.clone(), - token_account_info.clone(), - mint_info.clone(), - authority_info.clone(), - ], - seeds, - bump, - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn freeze<'info>( - account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - signer_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, -) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::freeze_account( - &token_program.key, - account_info.key, - mint_info.key, - owner_info.key, - &[signer_info.key], - )?, - &[ - token_program.clone(), - account_info.clone(), - mint_info.clone(), - owner_info.clone(), - signer_info.clone(), - ], - ) + pinocchio_token_2022::instructions::BurnChecked { + account: token_account_info, + mint: mint_info, + authority: authority_info, + amount, + decimals, + token_program, + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn freeze_signed<'info>( - account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - signer_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], +pub fn freeze( + account_info: &AccountView, + mint_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, signer_info.owner).1; - freeze_signed_with_bump( - account_info, - mint_info, - owner_info, - signer_info, + pinocchio_token_2022::instructions::FreezeAccount { + account: account_info, + mint: mint_info, + freeze_authority: authority_info, token_program, - seeds, - bump, - ) + } + .invoke() } #[inline(always)] -pub fn freeze_signed_with_bump<'info>( - account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - signer_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], - bump: u8, +pub fn freeze_signed( + account_info: &AccountView, + mint_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, + seeds: &[Seed; N], ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::freeze_account( - &token_program.key, - account_info.key, - mint_info.key, - owner_info.key, - &[signer_info.key], - )?, - &[ - token_program.clone(), - account_info.clone(), - mint_info.clone(), - owner_info.clone(), - signer_info.clone(), - ], - seeds, - bump, - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn initialize_mint<'info>( - mint_info: &AccountInfo<'info>, - mint_authority_info: &AccountInfo<'info>, - freeze_authority_info: Option<&AccountInfo<'info>>, - token_program: &AccountInfo<'info>, - rent_sysvar: &AccountInfo<'info>, - decimals: u8, -) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::initialize_mint( - &token_program.key, - mint_info.key, - mint_authority_info.key, - freeze_authority_info.map(|i| i.key), - decimals, - )?, - &[ - token_program.clone(), - mint_info.clone(), - mint_authority_info.clone(), - rent_sysvar.clone(), - ], - ) + pinocchio_token_2022::instructions::FreezeAccount { + account: account_info, + mint: mint_info, + freeze_authority: authority_info, + token_program, + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn initialize_mint_signed<'info>( - mint_info: &AccountInfo<'info>, - mint_authority_info: &AccountInfo<'info>, - freeze_authority_info: Option<&AccountInfo<'info>>, - token_program: &AccountInfo<'info>, - rent_sysvar: &AccountInfo<'info>, +pub fn initialize_mint( + mint_info: &AccountView, + rent_sysvar: &AccountView, + mint_authority: &Address, + freeze_authority: Option<&Address>, + token_program: &Address, decimals: u8, - seeds: &[&[u8]], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, mint_info.owner).1; - initialize_mint_signed_with_bump( - mint_info, - mint_authority_info, - freeze_authority_info, - token_program, + pinocchio_token_2022::instructions::InitializeMint { + mint: mint_info, rent_sysvar, decimals, - seeds, - bump, - ) -} - -#[inline(always)] -pub fn initialize_mint_signed_with_bump<'info>( - mint_info: &AccountInfo<'info>, - mint_authority_info: &AccountInfo<'info>, - freeze_authority_info: Option<&AccountInfo<'info>>, - token_program: &AccountInfo<'info>, - rent_sysvar: &AccountInfo<'info>, - decimals: u8, - seeds: &[&[u8]], - bump: u8, -) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::initialize_mint( - &token_program.key, - mint_info.key, - mint_authority_info.key, - freeze_authority_info.map(|i| i.key), - decimals, - )?, - &[ - token_program.clone(), - mint_info.clone(), - mint_authority_info.clone(), - rent_sysvar.clone(), - ], - seeds, - bump, - ) + mint_authority, + freeze_authority, + token_program, + } + .invoke() } /// Thaws a frozen SPL token account -/// #[inline(always)] -pub fn thaw_account<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn thaw_account( + token_account_info: &AccountView, + mint_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, ) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::thaw_account( - &token_program.key, - token_account_info.key, - mint_info.key, - authority_info.key, - &[authority_info.key], - )?, - &[ - token_program.clone(), - token_account_info.clone(), - mint_info.clone(), - authority_info.clone(), - ], - ) + pinocchio_token_2022::instructions::ThawAccount { + account: token_account_info, + mint: mint_info, + freeze_authority: authority_info, + token_program, + } + .invoke() } /// Thaws a frozen SPL token account using signed account -/// #[inline(always)] -pub fn thaw_account_signed<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], +pub fn thaw_account_signed( + token_account_info: &AccountView, + mint_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, + seeds: &[Seed; N], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - thaw_account_signed_with_bump( - token_account_info, - mint_info, - owner_info, - authority_info, - token_program, - seeds, - bump, - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn thaw_account_signed_with_bump<'info>( - token_account_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - signer_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], - bump: u8, -) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::thaw_account( - &token_program.key, - token_account_info.key, - mint_info.key, - owner_info.key, - &[signer_info.key], - )?, - &[ - token_program.clone(), - token_account_info.clone(), - mint_info.clone(), - owner_info.clone(), - signer_info.clone(), - ], - seeds, - bump, - ) + pinocchio_token_2022::instructions::ThawAccount { + account: token_account_info, + mint: mint_info, + freeze_authority: authority_info, + token_program, + } + .invoke_signed(&[signer_seeds]) } /// Set authority for an SPL token mint -/// #[inline(always)] -pub fn set_authority<'info>( - account_or_mint: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - new_authority_info: Option<&AccountInfo<'info>>, - authority_type: spl_token_2022::instruction::AuthorityType, - token_program: &AccountInfo<'info>, +pub fn set_authority( + account_or_mint: &AccountView, + authority_info: &AccountView, + new_authority: Option<&Address>, + authority_type: pinocchio_token_2022::instructions::AuthorityType, + token_program: &Address, ) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::set_authority( - &token_program.key, - account_or_mint.key, - new_authority_info.map(|i| i.key), - authority_type, - authority_info.key, - &[authority_info.key], - )?, - &[ - token_program.clone(), - account_or_mint.clone(), - authority_info.clone(), - ], - ) + pinocchio_token_2022::instructions::SetAuthority { + account: account_or_mint, + authority: authority_info, + authority_type, + new_authority, + token_program, + } + .invoke() } /// Set authority using signer seeds -/// #[inline(always)] -pub fn set_authority_signed<'info>( - account_or_mint: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - new_authority_info: Option<&AccountInfo<'info>>, - authority_type: spl_token_2022::instruction::AuthorityType, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], +pub fn set_authority_signed( + account_or_mint: &AccountView, + authority_info: &AccountView, + new_authority: Option<&Address>, + authority_type: pinocchio_token_2022::instructions::AuthorityType, + token_program: &Address, + seeds: &[Seed; N], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - set_authority_signed_with_bump( - account_or_mint, - authority_info, - new_authority_info, + let signer_seeds = Signer::from(seeds); + + pinocchio_token_2022::instructions::SetAuthority { + account: account_or_mint, + authority: authority_info, authority_type, + new_authority, token_program, - seeds, - bump, - ) -} - -#[inline(always)] -pub fn set_authority_signed_with_bump<'info>( - account_or_mint: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - new_authority_info: Option<&AccountInfo<'info>>, - authority_type: spl_token_2022::instruction::AuthorityType, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], - bump: u8, -) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::set_authority( - &token_program.key, - account_or_mint.key, - new_authority_info.map(|i| i.key), - authority_type, - authority_info.key, - &[authority_info.key], - )?, - &[ - token_program.clone(), - account_or_mint.clone(), - authority_info.clone(), - ], - seeds, - bump, - ) + } + .invoke_signed(&[signer_seeds]) } /// Revoke -/// #[inline(always)] -pub fn revoke<'info>( - source_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn revoke( + source_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, ) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::revoke( - &token_program.key, - source_info.key, - authority_info.key, - &[authority_info.key], - )?, - &[ - token_program.clone(), - source_info.clone(), - authority_info.clone(), - ], - ) + pinocchio_token_2022::instructions::Revoke { + source: source_info, + authority: authority_info, + token_program, + } + .invoke() } /// Revoke with signer seeds -/// #[inline(always)] -pub fn revoke_signed<'info>( - source_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], +pub fn revoke_signed( + source_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, + seeds: &[Seed; N], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, authority_info.owner).1; - revoke_signed_with_bump(source_info, authority_info, token_program, seeds, bump) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn revoke_signed_with_bump<'info>( - source_info: &AccountInfo<'info>, - authority_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - seeds: &[&[u8]], - bump: u8, -) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::revoke( - &token_program.key, - source_info.key, - authority_info.key, - &[authority_info.key], - )?, - &[ - token_program.clone(), - source_info.clone(), - authority_info.clone(), - ], - seeds, - bump, - ) + pinocchio_token_2022::instructions::Revoke { + source: source_info, + authority: authority_info, + token_program, + } + .invoke_signed(&[signer_seeds]) } -/// /// Approves a delegate. A delegate is given the authority over tokens on +/// Approves a delegate. A delegate is given the authority over tokens on /// behalf of the source account's owner. #[inline(always)] -pub fn approve<'info>( - source_info: &AccountInfo<'info>, - delegate_info: &AccountInfo<'info>, - owner_info: &AccountInfo<'info>, - signer_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn approve( + source_info: &AccountView, + delegate_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, amount: u64, ) -> ProgramResult { - solana_program::program::invoke( - &spl_token::instruction::approve( - &spl_token::ID, - source_info.key, - delegate_info.key, - owner_info.key, - &[signer_info.key], - amount, - )?, - &[ - token_program.clone(), - source_info.clone(), - delegate_info.clone(), - owner_info.clone(), - signer_info.clone(), - ], - ) + pinocchio_token_2022::instructions::Approve { + source: source_info, + delegate: delegate_info, + authority: authority_info, + amount, + token_program, + } + .invoke() } #[inline(always)] -pub fn approve_signed<'info>( - source_info: &AccountInfo<'info>, - delegate_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn approve_signed( + source_info: &AccountView, + delegate_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, amount: u64, - seeds: &[&[u8]], + seeds: &[Seed; N], ) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, &spl_token::ID).1; - approve_signed_with_bump( - source_info, - delegate_info, - token_program, + let signer_seeds = Signer::from(seeds); + + pinocchio_token_2022::instructions::Approve { + source: source_info, + delegate: delegate_info, + authority: authority_info, amount, - seeds, - bump, - ) + token_program, + } + .invoke_signed(&[signer_seeds]) } #[inline(always)] -pub fn approve_signed_with_bump<'info>( - source_info: &AccountInfo<'info>, - delegate_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn approve_checked( + source_info: &AccountView, + mint_info: &AccountView, + delegate_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, amount: u64, - seeds: &[&[u8]], - bump: u8, + decimals: u8, ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::approve( - &token_program.key, - source_info.key, - delegate_info.key, - delegate_info.key, - &[delegate_info.key], - amount, - )?, - &[ - token_program.clone(), - source_info.clone(), - delegate_info.clone(), - ], - seeds, - bump, - ) + pinocchio_token_2022::instructions::ApproveChecked { + source: source_info, + mint: mint_info, + delegate: delegate_info, + authority: authority_info, + amount, + decimals, + token_program, + } + .invoke() } #[inline(always)] -pub fn approve_checked<'info>( - source_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - delegate_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn approve_checked_signed( + source_info: &AccountView, + mint_info: &AccountView, + delegate_info: &AccountView, + authority_info: &AccountView, + token_program: &Address, amount: u64, decimals: u8, + seeds: &[Seed; N], ) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::approve_checked( - &token_program.key, - mint_info.key, - source_info.key, - delegate_info.key, - delegate_info.key, - &[delegate_info.key], - amount, - decimals, - )?, - &[ - token_program.clone(), - mint_info.clone(), - source_info.clone(), - delegate_info.clone(), - ], - ) -} + let signer_seeds = Signer::from(seeds); -#[inline(always)] -pub fn approve_checked_signed<'info>( - source_info: &AccountInfo<'info>, - delegate_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - amount: u64, - seeds: &[&[u8]], -) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, &spl_token::ID).1; - approve_signed_with_bump( - source_info, - delegate_info, - token_program, + pinocchio_token_2022::instructions::ApproveChecked { + source: source_info, + mint: mint_info, + delegate: delegate_info, + authority: authority_info, amount, - seeds, - bump, - ) -} - -#[inline(always)] -pub fn approve_checked_signed_with_bump<'info>( - source_info: &AccountInfo<'info>, - mint_info: &AccountInfo<'info>, - delegate_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - decimals: u8, - amount: u64, - seeds: &[&[u8]], - bump: u8, -) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::approve_checked( - &token_program.key, - source_info.key, - mint_info.key, - delegate_info.key, - delegate_info.key, - &[delegate_info.key], - amount, - decimals, - )?, - &[source_info.clone(), delegate_info.clone()], - seeds, - bump, - ) + decimals, + token_program, + } + .invoke_signed(&[signer_seeds]) } /// Initializes a multisignature account with N provided signers. #[inline(always)] -pub fn initialize_multisig<'info>( - multisig_info: &AccountInfo<'info>, - signer_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - n: u8, -) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::initialize_multisig( - &token_program.key, - multisig_info.key, - &[signer_info.key], - n, - )?, - &[token_program.clone(), signer_info.clone()], - ) -} - -#[inline(always)] -pub fn initialize_multisig_signed<'info>( - multisig_info: &AccountInfo<'info>, - signer_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, - m: u8, // number of multi signtures - seeds: &[&[u8]], -) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, &spl_token::ID).1; - initialize_multisig_signed_with_bump(multisig_info, signer_info, token_program, m, seeds, bump) -} - -#[inline(always)] -pub fn initialize_multisig_signed_with_bump<'info>( - multisig_info: &AccountInfo<'info>, - signer_info: &AccountInfo<'info>, - token_program: &AccountInfo<'info>, +pub fn initialize_multisig<'a, const S: usize>( + multisig_info: &AccountView, + rent_sysvar: &AccountView, + signers: &[&'a AccountView; S], + token_program: &Address, m: u8, - seeds: &[&[u8]], - bump: u8, -) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::initialize_multisig( - &token_program.key, - multisig_info.key, - &[signer_info.key], - m, - )?, - &[token_program.clone(), signer_info.clone()], - seeds, - bump, - ) -} - -///Like InitializeAccount2, but does not require the Rent sysvar to be provided -#[inline(always)] -pub fn sync_native(account_info: &AccountInfo) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::sync_native(account_info.owner, account_info.key)?, - &[account_info.clone()], - ) -} - -#[inline(always)] -pub fn sync_native_signed(account_info: &AccountInfo, seeds: &[&[u8]]) -> ProgramResult { - let bump = Pubkey::find_program_address(seeds, &spl_token::ID).1; - sync_native_signed_with_bump(account_info, seeds, bump) -} - -#[inline(always)] -pub fn sync_native_signed_with_bump( - account_info: &AccountInfo, - seeds: &[&[u8]], - bump: u8, ) -> ProgramResult { - invoke_signed_with_bump( - &spl_token_2022::instruction::sync_native(account_info.owner, account_info.key)?, - &[account_info.clone()], - seeds, - bump, - ) + pinocchio_token_2022::instructions::InitializeMultisig { + multisig: multisig_info, + rent_sysvar, + signers, + token_program, + m, + } + .invoke() } +/// Like InitializeAccount2, but does not require the Rent sysvar to be provided #[inline(always)] -pub fn get_account_data_size( - mint_info: &AccountInfo, - extension_types: &[spl_token_2022::extension::ExtensionType], -) -> ProgramResult { - solana_program::program::invoke( - &spl_token_2022::instruction::get_account_data_size( - mint_info.owner, - mint_info.key, - extension_types, - )?, - &[mint_info.clone()], - ) +pub fn sync_native(account_info: &AccountView, token_program: &Address) -> ProgramResult { + pinocchio_token_2022::instructions::SyncNative { + native_token: account_info, + token_program, + } + .invoke() } diff --git a/lib/src/spl/mod.rs b/lib/src/spl/mod.rs index 2bd0579..725ea0a 100644 --- a/lib/src/spl/mod.rs +++ b/lib/src/spl/mod.rs @@ -1,9 +1,9 @@ pub mod cpi; -pub mod mint; -pub mod token; -pub mod validation; +// pub mod mint; +// pub mod token; +// pub mod validation; pub use cpi::*; -pub use mint::*; -pub use token::*; -pub use validation::*; +// pub use mint::*; +// pub use token::*; +// pub use validation::*; From 393e06a6c88b450a162e540bb0d3a905dae3a7fc Mon Sep 17 00:00:00 2001 From: Perelyn <64838956+Perelyn-sama@users.noreply.github.com> Date: Fri, 23 Jan 2026 06:18:14 +0100 Subject: [PATCH 4/5] refactor account/lamports, account/validation and log --- lib/src/account/cpi.rs | 57 ----------------------------------- lib/src/account/lamports.rs | 17 +++++------ lib/src/account/mod.rs | 8 ++--- lib/src/account/validation.rs | 17 +++++++---- lib/src/lib.rs | 10 +++--- lib/src/log.rs | 9 +++--- 6 files changed, 32 insertions(+), 86 deletions(-) diff --git a/lib/src/account/cpi.rs b/lib/src/account/cpi.rs index bca2a56..d351300 100644 --- a/lib/src/account/cpi.rs +++ b/lib/src/account/cpi.rs @@ -24,55 +24,6 @@ pub fn invoke_signed( cpi::invoke_signed(instruction, account_views, &[signers_seeds]) } -// #[inline(always)] -// pub fn invoke_signed_with_bump( -// instruction: &Instruction, -// account_infos: &[&AccountInfo; ACCOUNTS], -// seeds: &[&[u8]; N], -// bump: &[u8], -// ) -> ProgramResult { -// // Create a buffer large enough for any reasonable PDA (max 16 seeds) -// let mut all_seeds: [&[u8]; 16] = [&[]; 16]; - -// // Copy input seeds -// all_seeds[..N].copy_from_slice(seeds); - -// // Append bump -// all_seeds[N] = bump; - -// // Use only the slice we need (N + 1 elements) -// pinocchio::cpi::invoke_signed(instruction, account_infos, &[&all_seeds[..N + 1]]) -// } - -/// Invokes a CPI with the provided signer seeds and bump. -// #[inline(always)] -// pub fn invoke_signed_with_bump( -// instruction: &Instruction, -// account_infos: &[&AccountInfo; ACCOUNTS], -// seeds: &[&[u8]], -// bump: &[u8], -// ) -> ProgramResult { -// let len = seeds.len(); -// let mut res; - -// for (i, e) in seeds.iter().enumerate() { -// res = [ -// Seed::from(seeds[i]), -// Seed::from(seeds[i + 1]), -// Seed::from(seeds[i + 2]), -// ]; -// } - -// // if seeds.len == 3 -// // - -// // Combine seeds -// let signer_seeds = Signer::from(seeds); - -// // Invoke CPI -// pinocchio::cpi::invoke_signed(instruction, account_infos, &[signer_seeds]) -// } - /// Creates a new account. #[inline(always)] pub fn create_account<'a, 'info>( @@ -97,14 +48,6 @@ pub fn create_account<'a, 'info>( Ok(()) } -// fn append(arr: [T; N], elem: T) -> [T; M] { - -// let mut result = [elem; M]; -// result[..N].copy_from_slice(&arr); -// result[N] = elem; -// result -// } - /// Creates a new program account. #[inline(always)] pub fn create_program_account<'a, 'info, T: Discriminator + Pod, const N: usize>( diff --git a/lib/src/account/lamports.rs b/lib/src/account/lamports.rs index 510b353..1eba36b 100644 --- a/lib/src/account/lamports.rs +++ b/lib/src/account/lamports.rs @@ -1,7 +1,5 @@ +use pinocchio::{error::ProgramError, AccountView}; use pinocchio_system::instructions::Transfer; -// use solana_program::{account_info::AccountInfo, program_error::ProgramError}; -use solana_account_view::AccountView; -use solana_program_error::ProgramError; pub trait LamportTransfer { fn send(&self, lamports: u64, to: &AccountView); @@ -17,12 +15,11 @@ impl LamportTransfer for AccountView { #[inline(always)] fn collect(&self, lamports: u64, from: &AccountView) -> Result<(), ProgramError> { - // Transfer { from, to, lamports }.invoke()?; - // solana_instruction_view::cpi::invoke::<2>(instruction, &[from, self]) - // solana_program::program::invoke( - // &solana_program::system_instruction::transfer(from.key, self.key, lamports), - // &[from.clone(), self.clone()], - // ) - Ok(()) + Transfer { + from, + to: &self, + lamports, + } + .invoke() } } diff --git a/lib/src/account/mod.rs b/lib/src/account/mod.rs index 9f0ac7c..acde9c3 100644 --- a/lib/src/account/mod.rs +++ b/lib/src/account/mod.rs @@ -1,11 +1,11 @@ mod close; mod cpi; mod deserialize; -// mod lamports; -// mod validation; +mod lamports; +mod validation; pub use close::*; pub use cpi::*; pub use deserialize::*; -// pub use lamports::*; -// pub use validation::*; +pub use lamports::*; +pub use validation::*; diff --git a/lib/src/account/validation.rs b/lib/src/account/validation.rs index 20a93a4..7367191 100644 --- a/lib/src/account/validation.rs +++ b/lib/src/account/validation.rs @@ -1,5 +1,4 @@ use bytemuck::Pod; -// use solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey}; use solana_account_view::AccountView; use solana_address::Address; use solana_program_error::ProgramError; @@ -8,6 +7,12 @@ use crate::trace; use super::{AccountDeserialize, Discriminator}; +/// `Sysvar1111111111111111111111111111111111111` +pub const SYSVAR_ID: Address = Address::new_from_array([ + 6, 167, 213, 23, 24, 117, 247, 41, 199, 61, 147, 64, 143, 33, 97, 32, 6, 126, 216, 140, 118, + 224, 140, 40, 127, 193, 148, 96, 0, 0, 0, 0, +]); + pub trait AccountInfoValidation { fn is_signer(&self) -> Result<&Self, ProgramError>; fn is_writable(&self) -> Result<&Self, ProgramError>; @@ -62,8 +67,7 @@ impl AccountInfoValidation for AccountView { #[track_caller] fn is_sysvar(&self, sysvar_id: &Address) -> Result<&Self, ProgramError> { - self.has_owner(&solana_program::sysvar::ID)? - .has_address(sysvar_id) + self.has_owner(&SYSVAR_ID)?.has_address(sysvar_id) } #[track_caller] @@ -107,17 +111,18 @@ impl AccountInfoValidation for AccountView { #[track_caller] fn has_owner(&self, owner: &Address) -> Result<&Self, ProgramError> { - if unsafe { self.owner() }.ne(owner) { + if self.owned_by(owner) { return Err(trace( format!( "Account has invalid owner {} != {}", - unsafe { *self.owner() }, + unsafe { self.owner() }, owner ) .as_str(), ProgramError::InvalidAccountOwner, )); } + Ok(self) } @@ -188,7 +193,7 @@ impl AsAccount for AccountView { self.has_owner(program_id)?; // Validate account data length. - let mut data = self.borrow_unchecked_mut(); + let data = self.borrow_unchecked_mut(); let expected_len = 8 + std::mem::size_of::(); if data.len() != expected_len { return Err(trace( diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 7994408..318a409 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1,19 +1,19 @@ mod account; -// mod log; +mod log; // pub mod macros; -// mod numeric; +mod numeric; #[cfg(feature = "spl")] mod spl; // mod utils; pub use account::*; -// pub use log::*; -// pub use numeric::*; +pub use log::*; +pub use numeric::*; #[cfg(feature = "spl")] pub use spl::*; // pub use utils::*; -// pub use bytemuck::{Pod, Zeroable}; +pub use bytemuck::{Pod, Zeroable}; // pub use num_enum::{IntoPrimitive, TryFromPrimitive}; // pub use solana_account_view::AccountView; // pub use solana_address::{address, Address}; diff --git a/lib/src/log.rs b/lib/src/log.rs index 45326ef..6b57568 100644 --- a/lib/src/log.rs +++ b/lib/src/log.rs @@ -1,16 +1,17 @@ -use solana_program::program_error::ProgramError; +use pinocchio::error::ProgramError; +use pinocchio_log::log; /// Logs a message. #[inline(always)] -pub fn log(msg: String) { - solana_program::log::sol_log(msg.as_str()); +pub fn log(msg: &str) { + log!("{}", msg); } /// Logs the call trace and returns the error. #[track_caller] pub fn trace(msg: &str, error: ProgramError) -> ProgramError { let caller = std::panic::Location::caller(); - log(format!("{}: {}", msg, caller)); + log(&format!("{}: {}", msg, caller)); error } From 56a51206aa4e8922e84feeee665b1358acdd661e Mon Sep 17 00:00:00 2001 From: Perelyn <64838956+Perelyn-sama@users.noreply.github.com> Date: Fri, 23 Jan 2026 06:31:06 +0100 Subject: [PATCH 5/5] refactor spl/token and spl/mint --- lib/src/spl/cpi.rs | 2 -- lib/src/spl/mint.rs | 30 +++++++++++++------------- lib/src/spl/mod.rs | 8 +++---- lib/src/spl/token.rs | 51 +++++++++++++++++++++++++------------------- 4 files changed, 48 insertions(+), 43 deletions(-) diff --git a/lib/src/spl/cpi.rs b/lib/src/spl/cpi.rs index 97b6adb..da6656d 100644 --- a/lib/src/spl/cpi.rs +++ b/lib/src/spl/cpi.rs @@ -3,8 +3,6 @@ use pinocchio::{ AccountView, Address, ProgramResult, }; -// use crate::account::invoke_signed_with_bump; - #[inline(always)] pub fn create_associated_token_account( funder_info: &AccountView, diff --git a/lib/src/spl/mint.rs b/lib/src/spl/mint.rs index bb5968c..5805ae1 100644 --- a/lib/src/spl/mint.rs +++ b/lib/src/spl/mint.rs @@ -1,43 +1,43 @@ -use solana_program::{program_option::COption, pubkey::Pubkey}; +use pinocchio::Address; pub enum Mint { - V0(spl_token::state::Mint), - V1(spl_token_2022::state::Mint), + V0(pinocchio_token::state::Mint), + V1(pinocchio_token_2022::state::Mint), } impl Mint { - pub fn mint_authority(&self) -> COption { + pub fn mint_authority(&self) -> Option<&Address> { match self { - Mint::V0(mint) => mint.mint_authority, - Mint::V1(mint) => mint.mint_authority, + Mint::V0(mint) => mint.mint_authority(), + Mint::V1(mint) => mint.mint_authority(), } } pub fn supply(&self) -> u64 { match self { - Mint::V0(mint) => mint.supply, - Mint::V1(mint) => mint.supply, + Mint::V0(mint) => mint.supply(), + Mint::V1(mint) => mint.supply(), } } pub fn decimals(&self) -> u8 { match self { - Mint::V0(mint) => mint.decimals, - Mint::V1(mint) => mint.decimals, + Mint::V0(mint) => mint.decimals(), + Mint::V1(mint) => mint.decimals(), } } pub fn is_initialized(&self) -> bool { match self { - Mint::V0(mint) => mint.is_initialized, - Mint::V1(mint) => mint.is_initialized, + Mint::V0(mint) => mint.is_initialized(), + Mint::V1(mint) => mint.is_initialized(), } } - pub fn freeze_authority(&self) -> COption { + pub fn freeze_authority(&self) -> Option<&Address> { match self { - Mint::V0(mint) => mint.freeze_authority, - Mint::V1(mint) => mint.freeze_authority, + Mint::V0(mint) => mint.freeze_authority(), + Mint::V1(mint) => mint.freeze_authority(), } } } diff --git a/lib/src/spl/mod.rs b/lib/src/spl/mod.rs index 725ea0a..e226411 100644 --- a/lib/src/spl/mod.rs +++ b/lib/src/spl/mod.rs @@ -1,9 +1,9 @@ pub mod cpi; -// pub mod mint; -// pub mod token; +pub mod mint; +pub mod token; // pub mod validation; pub use cpi::*; -// pub use mint::*; -// pub use token::*; +pub use mint::*; +pub use token::*; // pub use validation::*; diff --git a/lib/src/spl/token.rs b/lib/src/spl/token.rs index c4ba434..f38f785 100644 --- a/lib/src/spl/token.rs +++ b/lib/src/spl/token.rs @@ -1,36 +1,36 @@ -use solana_program::{program_option::COption, pubkey::Pubkey}; +use pinocchio::Address; pub enum TokenAccount { - V0(spl_token::state::Account), - V1(spl_token_2022::state::Account), + V0(pinocchio_token::state::TokenAccount), + V1(pinocchio_token_2022::state::TokenAccount), } impl TokenAccount { - pub fn mint(&self) -> Pubkey { + pub fn mint(&self) -> &Address { match self { - TokenAccount::V0(account) => account.mint, - TokenAccount::V1(account) => account.mint, + TokenAccount::V0(account) => account.mint(), + TokenAccount::V1(account) => account.mint(), } } - pub fn owner(&self) -> Pubkey { + pub fn owner(&self) -> &Address { match self { - TokenAccount::V0(account) => account.owner, - TokenAccount::V1(account) => account.owner, + TokenAccount::V0(account) => account.owner(), + TokenAccount::V1(account) => account.owner(), } } pub fn amount(&self) -> u64 { match self { - TokenAccount::V0(account) => account.amount, - TokenAccount::V1(account) => account.amount, + TokenAccount::V0(account) => account.amount(), + TokenAccount::V1(account) => account.amount(), } } - pub fn delegate(&self) -> COption { + pub fn delegate(&self) -> Option<&Address> { match self { - TokenAccount::V0(account) => account.delegate, - TokenAccount::V1(account) => account.delegate, + TokenAccount::V0(account) => account.delegate(), + TokenAccount::V1(account) => account.delegate(), } } @@ -41,24 +41,31 @@ impl TokenAccount { } } - pub fn is_native(&self) -> COption { + pub fn is_native(&self) -> bool { match self { - TokenAccount::V0(account) => account.is_native, - TokenAccount::V1(account) => account.is_native, + TokenAccount::V0(account) => account.is_native(), + TokenAccount::V1(account) => account.is_native(), + } + } + + pub fn native_amount(&self) -> Option { + match self { + TokenAccount::V0(account) => account.native_amount(), + TokenAccount::V1(account) => account.native_amount(), } } pub fn delegated_amount(&self) -> u64 { match self { - TokenAccount::V0(account) => account.delegated_amount, - TokenAccount::V1(account) => account.delegated_amount, + TokenAccount::V0(account) => account.delegated_amount(), + TokenAccount::V1(account) => account.delegated_amount(), } } - pub fn close_authority(&self) -> COption { + pub fn close_authority(&self) -> Option<&Address> { match self { - TokenAccount::V0(account) => account.close_authority, - TokenAccount::V1(account) => account.close_authority, + TokenAccount::V0(account) => account.close_authority(), + TokenAccount::V1(account) => account.close_authority(), } } }