From 68012e9a4d3bcdbd4b429356e45151a81633f90c Mon Sep 17 00:00:00 2001 From: Gabe Rodriguez Date: Mon, 20 Apr 2026 08:03:01 -0700 Subject: [PATCH] no-std clients --- .changeset/violet-brooms-brake.md | 16 ++++++++++ Cargo.lock | 6 ++-- Cargo.toml | 8 ++--- e2e/anchor/src/generated/accounts/guard_v1.rs | 31 +++++++++++-------- .../generated/instructions/create_guard.rs | 7 +++-- .../src/generated/instructions/execute.rs | 6 ++-- .../src/generated/instructions/initialize.rs | 4 ++- .../generated/instructions/update_guard.rs | 6 ++-- e2e/anchor/src/generated/mod.rs | 2 ++ e2e/anchor/src/generated/types/cpi_rule.rs | 1 + .../metadata_additional_field_restriction.rs | 2 ++ .../types/metadata_additional_field_rule.rs | 1 + e2e/anchor/src/lib.rs | 4 +++ .../generated/instructions/instruction1.rs | 4 ++- .../generated/instructions/instruction2.rs | 4 ++- .../generated/instructions/instruction3.rs | 4 ++- .../generated/instructions/instruction4.rs | 6 ++-- .../generated/instructions/instruction5.rs | 6 ++-- .../generated/instructions/instruction6.rs | 4 ++- .../generated/instructions/instruction7.rs | 4 ++- e2e/dummy/src/generated/mod.rs | 2 ++ e2e/dummy/src/lib.rs | 4 +++ .../src/generated/instructions/add_memo.rs | 6 ++-- e2e/memo/src/generated/mod.rs | 2 ++ e2e/memo/src/lib.rs | 4 +++ e2e/system/src/generated/accounts/nonce.rs | 30 ++++++++++-------- .../instructions/advance_nonce_account.rs | 4 ++- .../src/generated/instructions/allocate.rs | 6 ++-- .../instructions/allocate_with_seed.rs | 7 +++-- .../src/generated/instructions/assign.rs | 6 ++-- .../instructions/assign_with_seed.rs | 7 +++-- .../instructions/authorize_nonce_account.rs | 6 ++-- .../generated/instructions/create_account.rs | 6 ++-- .../instructions/create_account_with_seed.rs | 7 +++-- .../instructions/initialize_nonce_account.rs | 6 ++-- .../generated/instructions/transfer_sol.rs | 6 ++-- .../instructions/transfer_sol_with_seed.rs | 7 +++-- .../instructions/upgrade_nonce_account.rs | 4 ++- .../instructions/withdraw_nonce_account.rs | 6 ++-- e2e/system/src/generated/mod.rs | 2 ++ e2e/system/src/generated/types/nonce_state.rs | 1 + .../src/generated/types/nonce_version.rs | 1 + e2e/system/src/lib.rs | 4 +++ public/templates/accountsPage.njk | 26 ++++++++-------- public/templates/instructionsPage.njk | 4 +-- public/templates/rootMod.njk | 2 ++ src/getRenderMapVisitor.ts | 2 +- src/getTypeManifestVisitor.ts | 11 ++++--- src/renderValueNodeVisitor.ts | 12 ++++--- src/renderVisitor.ts | 2 ++ src/utils/cargoToml.ts | 8 ++--- src/utils/index.ts | 1 + src/utils/noStd.ts | 23 ++++++++++++++ src/utils/traitOptions.ts | 2 +- test/utils/noStd.test.ts | 30 ++++++++++++++++++ test/utils/traitOptions.test.ts | 6 ++-- 56 files changed, 280 insertions(+), 109 deletions(-) create mode 100644 .changeset/violet-brooms-brake.md create mode 100644 src/utils/noStd.ts create mode 100644 test/utils/noStd.test.ts diff --git a/.changeset/violet-brooms-brake.md b/.changeset/violet-brooms-brake.md new file mode 100644 index 0000000..a6578ea --- /dev/null +++ b/.changeset/violet-brooms-brake.md @@ -0,0 +1,16 @@ +--- +'@codama/renderers-rust': major +--- + +Make generated Rust clients `no_std`-compatible by default. + +Generated Rust output now emits `extern crate alloc`, replaces `std` collection and string usage with `alloc`-backed equivalents, and fails rendering if any `std::` references remain in generated files. + +This changes part of the generated API surface: +- map and set types now use `BTreeMap` and `BTreeSet` +- generated scalar enums now also derive `Ord` by default +- Borsh serialization and deserialization helpers now return `borsh::io::Error` instead of `std::io::Error` + +When syncing Cargo dependencies, the renderer now disables default features for crates that would otherwise pull in `std` and upgrades `thiserror` to v2 with `default-features = false`. + +This is a breaking change because upgrading changes generated Rust types, error types, and synced Cargo dependency declarations for existing clients. diff --git a/Cargo.lock b/Cargo.lock index da4d9bb..d8c9971 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -705,7 +705,7 @@ dependencies = [ "solana-cpi 3.1.0", "solana-instruction 3.2.0", "solana-program-error 3.0.0", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] @@ -750,7 +750,7 @@ dependencies = [ "solana-instruction 3.2.0", "solana-program-error 3.0.0", "spl-collections", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] @@ -768,7 +768,7 @@ dependencies = [ "solana-cpi 3.1.0", "solana-instruction 3.2.0", "solana-program-error 3.0.0", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f412555..5d882ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,16 +4,16 @@ resolver = "2" [workspace.dependencies] anchor-lang = "~0.31" -borsh = "^1.0" +borsh = { version = "^1.0", default-features = false, features = ["derive"] } num-derive = "^0.4" -num-traits = "^0.2" +num-traits = { version = "^0.2", default-features = false } solana-account = "~3.0" solana-account-info = "~3.1" solana-address = "~2.2" solana-client = "~3.0" solana-cpi = "~3.1" solana-decode-error = "~2.3" -solana-instruction = "~3.2" +solana-instruction = { version = "~3.2", default-features = false } solana-program-error = "~3.0" spl-collections = "0.1.1" -thiserror = "^1.0" +thiserror = { version = "^2.0", default-features = false } diff --git a/e2e/anchor/src/generated/accounts/guard_v1.rs b/e2e/anchor/src/generated/accounts/guard_v1.rs index 6575b57..81f40d2 100644 --- a/e2e/anchor/src/generated/accounts/guard_v1.rs +++ b/e2e/anchor/src/generated/accounts/guard_v1.rs @@ -8,6 +8,7 @@ use crate::generated::types::CpiRule; use crate::generated::types::MetadataAdditionalFieldRule; use crate::generated::types::TransferAmountRule; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -31,14 +32,14 @@ pub const GUARD_V1_DISCRIMINATOR: [u8; 8] = [185, 149, 156, 78, 245, 108, 172, 6 impl GuardV1 { #[inline(always)] - pub fn from_bytes(data: &[u8]) -> Result { + pub fn from_bytes(data: &[u8]) -> Result { let mut data = data; Self::deserialize(&mut data) } } impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GuardV1 { - type Error = std::io::Error; + type Error = borsh::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { let mut data: &[u8] = &(*account_info.data).borrow(); @@ -50,7 +51,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GuardV1 { pub fn fetch_guard_v1( rpc: &solana_client::rpc_client::RpcClient, address: &solana_address::Address, -) -> Result, std::io::Error> { +) -> Result, borsh::io::Error> { let accounts = fetch_all_guard_v1(rpc, &[*address])?; Ok(accounts[0].clone()) } @@ -59,16 +60,19 @@ pub fn fetch_guard_v1( pub fn fetch_all_guard_v1( rpc: &solana_client::rpc_client::RpcClient, addresses: &[solana_address::Address], -) -> Result>, std::io::Error> { +) -> Result>, borsh::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::other(e.to_string()))?; - let mut decoded_accounts: Vec> = Vec::new(); + .map_err(|e| borsh::io::Error::other(alloc::format!("{e}")))?; + let mut decoded_accounts: alloc::vec::Vec> = + alloc::vec::Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( - "Account not found: {address}" - )))?; + let account = accounts[i] + .as_ref() + .ok_or(borsh::io::Error::other(alloc::format!( + "Account not found: {address}" + )))?; let data = GuardV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -83,7 +87,7 @@ pub fn fetch_all_guard_v1( pub fn fetch_maybe_guard_v1( rpc: &solana_client::rpc_client::RpcClient, address: &solana_address::Address, -) -> Result, std::io::Error> { +) -> Result, borsh::io::Error> { let accounts = fetch_all_maybe_guard_v1(rpc, &[*address])?; Ok(accounts[0].clone()) } @@ -92,11 +96,12 @@ pub fn fetch_maybe_guard_v1( pub fn fetch_all_maybe_guard_v1( rpc: &solana_client::rpc_client::RpcClient, addresses: &[solana_address::Address], -) -> Result>, std::io::Error> { +) -> Result>, borsh::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::other(e.to_string()))?; - let mut decoded_accounts: Vec> = Vec::new(); + .map_err(|e| borsh::io::Error::other(alloc::format!("{e}")))?; + let mut decoded_accounts: alloc::vec::Vec> = + alloc::vec::Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { diff --git a/e2e/anchor/src/generated/instructions/create_guard.rs b/e2e/anchor/src/generated/instructions/create_guard.rs index fd28a57..fb62779 100644 --- a/e2e/anchor/src/generated/instructions/create_guard.rs +++ b/e2e/anchor/src/generated/instructions/create_guard.rs @@ -8,6 +8,9 @@ use crate::generated::types::CpiRule; use crate::generated::types::MetadataAdditionalFieldRule; use crate::generated::types::TransferAmountRule; +use alloc::boxed::Box; +use alloc::string::String; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -93,7 +96,7 @@ impl CreateGuardInstructionData { } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -115,7 +118,7 @@ pub struct CreateGuardInstructionArgs { } impl CreateGuardInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/anchor/src/generated/instructions/execute.rs b/e2e/anchor/src/generated/instructions/execute.rs index 410cbe4..c213812 100644 --- a/e2e/anchor/src/generated/instructions/execute.rs +++ b/e2e/anchor/src/generated/instructions/execute.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -91,7 +93,7 @@ impl ExecuteInstructionData { } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -108,7 +110,7 @@ pub struct ExecuteInstructionArgs { } impl ExecuteInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/anchor/src/generated/instructions/initialize.rs b/e2e/anchor/src/generated/instructions/initialize.rs index ce30b3c..bba0b6b 100644 --- a/e2e/anchor/src/generated/instructions/initialize.rs +++ b/e2e/anchor/src/generated/instructions/initialize.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -79,7 +81,7 @@ impl InitializeInstructionData { } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/anchor/src/generated/instructions/update_guard.rs b/e2e/anchor/src/generated/instructions/update_guard.rs index 9eb70a1..9e5b980 100644 --- a/e2e/anchor/src/generated/instructions/update_guard.rs +++ b/e2e/anchor/src/generated/instructions/update_guard.rs @@ -8,6 +8,8 @@ use crate::generated::types::CpiRule; use crate::generated::types::MetadataAdditionalFieldRule; use crate::generated::types::TransferAmountRule; +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -86,7 +88,7 @@ impl UpdateGuardInstructionData { } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -105,7 +107,7 @@ pub struct UpdateGuardInstructionArgs { } impl UpdateGuardInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/anchor/src/generated/mod.rs b/e2e/anchor/src/generated/mod.rs index e0d740a..31d7cd6 100644 --- a/e2e/anchor/src/generated/mod.rs +++ b/e2e/anchor/src/generated/mod.rs @@ -5,6 +5,8 @@ //! //! +extern crate alloc; + pub mod accounts; pub mod errors; pub mod instructions; diff --git a/e2e/anchor/src/generated/types/cpi_rule.rs b/e2e/anchor/src/generated/types/cpi_rule.rs index 2b31887..990e44b 100644 --- a/e2e/anchor/src/generated/types/cpi_rule.rs +++ b/e2e/anchor/src/generated/types/cpi_rule.rs @@ -5,6 +5,7 @@ //! //! +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; diff --git a/e2e/anchor/src/generated/types/metadata_additional_field_restriction.rs b/e2e/anchor/src/generated/types/metadata_additional_field_restriction.rs index e4e11d5..ddf0517 100644 --- a/e2e/anchor/src/generated/types/metadata_additional_field_restriction.rs +++ b/e2e/anchor/src/generated/types/metadata_additional_field_restriction.rs @@ -5,6 +5,8 @@ //! //! +use alloc::string::String; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; diff --git a/e2e/anchor/src/generated/types/metadata_additional_field_rule.rs b/e2e/anchor/src/generated/types/metadata_additional_field_rule.rs index 5898536..b15f58c 100644 --- a/e2e/anchor/src/generated/types/metadata_additional_field_rule.rs +++ b/e2e/anchor/src/generated/types/metadata_additional_field_rule.rs @@ -6,6 +6,7 @@ //! use crate::generated::types::MetadataAdditionalFieldRestriction; +use alloc::string::String; use borsh::BorshDeserialize; use borsh::BorshSerialize; diff --git a/e2e/anchor/src/lib.rs b/e2e/anchor/src/lib.rs index 9974b79..1cbf302 100644 --- a/e2e/anchor/src/lib.rs +++ b/e2e/anchor/src/lib.rs @@ -1,3 +1,7 @@ +#![no_std] + +extern crate alloc; + mod generated; pub use generated::programs::WEN_TRANSFER_GUARD_ID as ID; diff --git a/e2e/dummy/src/generated/instructions/instruction1.rs b/e2e/dummy/src/generated/instructions/instruction1.rs index cae4c09..a517d29 100644 --- a/e2e/dummy/src/generated/instructions/instruction1.rs +++ b/e2e/dummy/src/generated/instructions/instruction1.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -42,7 +44,7 @@ impl Instruction1InstructionData { Self {} } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/dummy/src/generated/instructions/instruction2.rs b/e2e/dummy/src/generated/instructions/instruction2.rs index d946ef0..d74c05b 100644 --- a/e2e/dummy/src/generated/instructions/instruction2.rs +++ b/e2e/dummy/src/generated/instructions/instruction2.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -42,7 +44,7 @@ impl Instruction2InstructionData { Self {} } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/dummy/src/generated/instructions/instruction3.rs b/e2e/dummy/src/generated/instructions/instruction3.rs index 876b035..89c9bcc 100644 --- a/e2e/dummy/src/generated/instructions/instruction3.rs +++ b/e2e/dummy/src/generated/instructions/instruction3.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -46,7 +48,7 @@ impl Instruction3InstructionData { Self { discriminator: 42 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/dummy/src/generated/instructions/instruction4.rs b/e2e/dummy/src/generated/instructions/instruction4.rs index 860b06e..c908a3f 100644 --- a/e2e/dummy/src/generated/instructions/instruction4.rs +++ b/e2e/dummy/src/generated/instructions/instruction4.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -48,7 +50,7 @@ impl Instruction4InstructionData { Self {} } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -65,7 +67,7 @@ pub struct Instruction4InstructionArgs { } impl Instruction4InstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/dummy/src/generated/instructions/instruction5.rs b/e2e/dummy/src/generated/instructions/instruction5.rs index da1301e..0d0c860 100644 --- a/e2e/dummy/src/generated/instructions/instruction5.rs +++ b/e2e/dummy/src/generated/instructions/instruction5.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -48,7 +50,7 @@ impl Instruction5InstructionData { Self {} } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -65,7 +67,7 @@ pub struct Instruction5InstructionArgs { } impl Instruction5InstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/dummy/src/generated/instructions/instruction6.rs b/e2e/dummy/src/generated/instructions/instruction6.rs index a6762bf..4c2f6ba 100644 --- a/e2e/dummy/src/generated/instructions/instruction6.rs +++ b/e2e/dummy/src/generated/instructions/instruction6.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -45,7 +47,7 @@ impl Instruction6InstructionData { Self {} } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/dummy/src/generated/instructions/instruction7.rs b/e2e/dummy/src/generated/instructions/instruction7.rs index fff4818..5100e6b 100644 --- a/e2e/dummy/src/generated/instructions/instruction7.rs +++ b/e2e/dummy/src/generated/instructions/instruction7.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -52,7 +54,7 @@ impl Instruction7InstructionData { Self {} } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/dummy/src/generated/mod.rs b/e2e/dummy/src/generated/mod.rs index 9c64a4b..162aae7 100644 --- a/e2e/dummy/src/generated/mod.rs +++ b/e2e/dummy/src/generated/mod.rs @@ -5,6 +5,8 @@ //! //! +extern crate alloc; + pub mod errors; pub mod instructions; pub mod programs; diff --git a/e2e/dummy/src/lib.rs b/e2e/dummy/src/lib.rs index 03cae83..7a52057 100644 --- a/e2e/dummy/src/lib.rs +++ b/e2e/dummy/src/lib.rs @@ -1,3 +1,7 @@ +#![no_std] + +extern crate alloc; + mod generated; pub use generated::programs::DUMMY_ID as ID; diff --git a/e2e/memo/src/generated/instructions/add_memo.rs b/e2e/memo/src/generated/instructions/add_memo.rs index ab0460e..8d5b799 100644 --- a/e2e/memo/src/generated/instructions/add_memo.rs +++ b/e2e/memo/src/generated/instructions/add_memo.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use spl_collections::TrailingStr; @@ -46,7 +48,7 @@ impl AddMemoInstructionData { Self {} } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -63,7 +65,7 @@ pub struct AddMemoInstructionArgs { } impl AddMemoInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/memo/src/generated/mod.rs b/e2e/memo/src/generated/mod.rs index 9c64a4b..162aae7 100644 --- a/e2e/memo/src/generated/mod.rs +++ b/e2e/memo/src/generated/mod.rs @@ -5,6 +5,8 @@ //! //! +extern crate alloc; + pub mod errors; pub mod instructions; pub mod programs; diff --git a/e2e/memo/src/lib.rs b/e2e/memo/src/lib.rs index 44c77a4..4ead952 100644 --- a/e2e/memo/src/lib.rs +++ b/e2e/memo/src/lib.rs @@ -1,3 +1,7 @@ +#![no_std] + +extern crate alloc; + mod generated; pub use generated::programs::MEMO_ID as ID; diff --git a/e2e/system/src/generated/accounts/nonce.rs b/e2e/system/src/generated/accounts/nonce.rs index c46f6d1..ea8903d 100644 --- a/e2e/system/src/generated/accounts/nonce.rs +++ b/e2e/system/src/generated/accounts/nonce.rs @@ -24,14 +24,14 @@ impl Nonce { pub const LEN: usize = 80; #[inline(always)] - pub fn from_bytes(data: &[u8]) -> Result { + pub fn from_bytes(data: &[u8]) -> Result { let mut data = data; Self::deserialize(&mut data) } } impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for Nonce { - type Error = std::io::Error; + type Error = borsh::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { let mut data: &[u8] = &(*account_info.data).borrow(); @@ -43,7 +43,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for Nonce { pub fn fetch_nonce( rpc: &solana_client::rpc_client::RpcClient, address: &solana_address::Address, -) -> Result, std::io::Error> { +) -> Result, borsh::io::Error> { let accounts = fetch_all_nonce(rpc, &[*address])?; Ok(accounts[0].clone()) } @@ -52,16 +52,19 @@ pub fn fetch_nonce( pub fn fetch_all_nonce( rpc: &solana_client::rpc_client::RpcClient, addresses: &[solana_address::Address], -) -> Result>, std::io::Error> { +) -> Result>, borsh::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::other(e.to_string()))?; - let mut decoded_accounts: Vec> = Vec::new(); + .map_err(|e| borsh::io::Error::other(alloc::format!("{e}")))?; + let mut decoded_accounts: alloc::vec::Vec> = + alloc::vec::Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( - "Account not found: {address}" - )))?; + let account = accounts[i] + .as_ref() + .ok_or(borsh::io::Error::other(alloc::format!( + "Account not found: {address}" + )))?; let data = Nonce::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -76,7 +79,7 @@ pub fn fetch_all_nonce( pub fn fetch_maybe_nonce( rpc: &solana_client::rpc_client::RpcClient, address: &solana_address::Address, -) -> Result, std::io::Error> { +) -> Result, borsh::io::Error> { let accounts = fetch_all_maybe_nonce(rpc, &[*address])?; Ok(accounts[0].clone()) } @@ -85,11 +88,12 @@ pub fn fetch_maybe_nonce( pub fn fetch_all_maybe_nonce( rpc: &solana_client::rpc_client::RpcClient, addresses: &[solana_address::Address], -) -> Result>, std::io::Error> { +) -> Result>, borsh::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::other(e.to_string()))?; - let mut decoded_accounts: Vec> = Vec::new(); + .map_err(|e| borsh::io::Error::other(alloc::format!("{e}")))?; + let mut decoded_accounts: alloc::vec::Vec> = + alloc::vec::Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { diff --git a/e2e/system/src/generated/instructions/advance_nonce_account.rs b/e2e/system/src/generated/instructions/advance_nonce_account.rs index 4858fa9..79af709 100644 --- a/e2e/system/src/generated/instructions/advance_nonce_account.rs +++ b/e2e/system/src/generated/instructions/advance_nonce_account.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -66,7 +68,7 @@ impl AdvanceNonceAccountInstructionData { Self { discriminator: 4 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/allocate.rs b/e2e/system/src/generated/instructions/allocate.rs index ef7989f..f3b07b9 100644 --- a/e2e/system/src/generated/instructions/allocate.rs +++ b/e2e/system/src/generated/instructions/allocate.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -52,7 +54,7 @@ impl AllocateInstructionData { Self { discriminator: 8 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -69,7 +71,7 @@ pub struct AllocateInstructionArgs { } impl AllocateInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/allocate_with_seed.rs b/e2e/system/src/generated/instructions/allocate_with_seed.rs index 0064540..12633a7 100644 --- a/e2e/system/src/generated/instructions/allocate_with_seed.rs +++ b/e2e/system/src/generated/instructions/allocate_with_seed.rs @@ -5,6 +5,9 @@ //! //! +use alloc::boxed::Box; +use alloc::string::String; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -65,7 +68,7 @@ impl AllocateWithSeedInstructionData { Self { discriminator: 9 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -85,7 +88,7 @@ pub struct AllocateWithSeedInstructionArgs { } impl AllocateWithSeedInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/assign.rs b/e2e/system/src/generated/instructions/assign.rs index 4ccc263..a1468a7 100644 --- a/e2e/system/src/generated/instructions/assign.rs +++ b/e2e/system/src/generated/instructions/assign.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -53,7 +55,7 @@ impl AssignInstructionData { Self { discriminator: 1 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -70,7 +72,7 @@ pub struct AssignInstructionArgs { } impl AssignInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/assign_with_seed.rs b/e2e/system/src/generated/instructions/assign_with_seed.rs index bd88c2f..8bb0834 100644 --- a/e2e/system/src/generated/instructions/assign_with_seed.rs +++ b/e2e/system/src/generated/instructions/assign_with_seed.rs @@ -5,6 +5,9 @@ //! //! +use alloc::boxed::Box; +use alloc::string::String; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -62,7 +65,7 @@ impl AssignWithSeedInstructionData { Self { discriminator: 10 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -81,7 +84,7 @@ pub struct AssignWithSeedInstructionArgs { } impl AssignWithSeedInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/authorize_nonce_account.rs b/e2e/system/src/generated/instructions/authorize_nonce_account.rs index e881144..1acddbb 100644 --- a/e2e/system/src/generated/instructions/authorize_nonce_account.rs +++ b/e2e/system/src/generated/instructions/authorize_nonce_account.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -67,7 +69,7 @@ impl AuthorizeNonceAccountInstructionData { Self { discriminator: 7 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -84,7 +86,7 @@ pub struct AuthorizeNonceAccountInstructionArgs { } impl AuthorizeNonceAccountInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/create_account.rs b/e2e/system/src/generated/instructions/create_account.rs index b455e4c..83af3f7 100644 --- a/e2e/system/src/generated/instructions/create_account.rs +++ b/e2e/system/src/generated/instructions/create_account.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -59,7 +61,7 @@ impl CreateAccountInstructionData { Self { discriminator: 0 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -78,7 +80,7 @@ pub struct CreateAccountInstructionArgs { } impl CreateAccountInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/create_account_with_seed.rs b/e2e/system/src/generated/instructions/create_account_with_seed.rs index 97676e7..4e28ec5 100644 --- a/e2e/system/src/generated/instructions/create_account_with_seed.rs +++ b/e2e/system/src/generated/instructions/create_account_with_seed.rs @@ -5,6 +5,9 @@ //! //! +use alloc::boxed::Box; +use alloc::string::String; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -70,7 +73,7 @@ impl CreateAccountWithSeedInstructionData { Self { discriminator: 3 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -91,7 +94,7 @@ pub struct CreateAccountWithSeedInstructionArgs { } impl CreateAccountWithSeedInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/initialize_nonce_account.rs b/e2e/system/src/generated/instructions/initialize_nonce_account.rs index f453f48..c9dd089 100644 --- a/e2e/system/src/generated/instructions/initialize_nonce_account.rs +++ b/e2e/system/src/generated/instructions/initialize_nonce_account.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -73,7 +75,7 @@ impl InitializeNonceAccountInstructionData { Self { discriminator: 6 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -90,7 +92,7 @@ pub struct InitializeNonceAccountInstructionArgs { } impl InitializeNonceAccountInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/transfer_sol.rs b/e2e/system/src/generated/instructions/transfer_sol.rs index 6403821..2cd04c4 100644 --- a/e2e/system/src/generated/instructions/transfer_sol.rs +++ b/e2e/system/src/generated/instructions/transfer_sol.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -58,7 +60,7 @@ impl TransferSolInstructionData { Self { discriminator: 2 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -75,7 +77,7 @@ pub struct TransferSolInstructionArgs { } impl TransferSolInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/transfer_sol_with_seed.rs b/e2e/system/src/generated/instructions/transfer_sol_with_seed.rs index 3fd3668..ab6ce50 100644 --- a/e2e/system/src/generated/instructions/transfer_sol_with_seed.rs +++ b/e2e/system/src/generated/instructions/transfer_sol_with_seed.rs @@ -5,6 +5,9 @@ //! //! +use alloc::boxed::Box; +use alloc::string::String; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -70,7 +73,7 @@ impl TransferSolWithSeedInstructionData { Self { discriminator: 11 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -89,7 +92,7 @@ pub struct TransferSolWithSeedInstructionArgs { } impl TransferSolWithSeedInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/upgrade_nonce_account.rs b/e2e/system/src/generated/instructions/upgrade_nonce_account.rs index 7de98bc..6b903b4 100644 --- a/e2e/system/src/generated/instructions/upgrade_nonce_account.rs +++ b/e2e/system/src/generated/instructions/upgrade_nonce_account.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -54,7 +56,7 @@ impl UpgradeNonceAccountInstructionData { Self { discriminator: 12 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/instructions/withdraw_nonce_account.rs b/e2e/system/src/generated/instructions/withdraw_nonce_account.rs index da43d7d..84fdec2 100644 --- a/e2e/system/src/generated/instructions/withdraw_nonce_account.rs +++ b/e2e/system/src/generated/instructions/withdraw_nonce_account.rs @@ -5,6 +5,8 @@ //! //! +use alloc::boxed::Box; +use alloc::vec::Vec; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -84,7 +86,7 @@ impl WithdrawNonceAccountInstructionData { Self { discriminator: 5 } } - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } @@ -101,7 +103,7 @@ pub struct WithdrawNonceAccountInstructionArgs { } impl WithdrawNonceAccountInstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/e2e/system/src/generated/mod.rs b/e2e/system/src/generated/mod.rs index e0d740a..31d7cd6 100644 --- a/e2e/system/src/generated/mod.rs +++ b/e2e/system/src/generated/mod.rs @@ -5,6 +5,8 @@ //! //! +extern crate alloc; + pub mod accounts; pub mod errors; pub mod instructions; diff --git a/e2e/system/src/generated/types/nonce_state.rs b/e2e/system/src/generated/types/nonce_state.rs index de390cf..297b17e 100644 --- a/e2e/system/src/generated/types/nonce_state.rs +++ b/e2e/system/src/generated/types/nonce_state.rs @@ -18,6 +18,7 @@ use num_derive::FromPrimitive; PartialEq, Copy, PartialOrd, + Ord, Hash, FromPrimitive, )] diff --git a/e2e/system/src/generated/types/nonce_version.rs b/e2e/system/src/generated/types/nonce_version.rs index 906432e..846db7e 100644 --- a/e2e/system/src/generated/types/nonce_version.rs +++ b/e2e/system/src/generated/types/nonce_version.rs @@ -18,6 +18,7 @@ use num_derive::FromPrimitive; PartialEq, Copy, PartialOrd, + Ord, Hash, FromPrimitive, )] diff --git a/e2e/system/src/lib.rs b/e2e/system/src/lib.rs index 45066cd..20c8173 100644 --- a/e2e/system/src/lib.rs +++ b/e2e/system/src/lib.rs @@ -1,3 +1,7 @@ +#![no_std] + +extern crate alloc; + mod generated; pub use generated::programs::SYSTEM_ID as ID; diff --git a/public/templates/accountsPage.njk b/public/templates/accountsPage.njk index 6d718d9..ba42fc4 100644 --- a/public/templates/accountsPage.njk +++ b/public/templates/accountsPage.njk @@ -73,7 +73,7 @@ impl {{ account.name | pascalCase }} { {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} &{{ seed.name | snakeCase }}, {% else %} - {{ seed.name | snakeCase }}.to_string().as_ref(), + alloc::string::ToString::to_string(&{{ seed.name | snakeCase }}).as_ref(), {% endif %} {% endfor %} &[bump], @@ -105,7 +105,7 @@ impl {{ account.name | pascalCase }} { {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} &{{ seed.name | snakeCase }}, {% else %} - {{ seed.name | snakeCase }}.to_string().as_ref(), + alloc::string::ToString::to_string(&{{ seed.name | snakeCase }}).as_ref(), {% endif %} {% endfor %} ], @@ -115,14 +115,14 @@ impl {{ account.name | pascalCase }} { {% endif %} #[inline(always)] - pub fn from_bytes(data: &[u8]) -> Result { + pub fn from_bytes(data: &[u8]) -> Result { let mut data = data; Self::deserialize(&mut data) } } impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for {{ account.name | pascalCase }} { - type Error = std::io::Error; + type Error = borsh::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { let mut data: &[u8] = &(*account_info.data).borrow(); @@ -134,7 +134,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for {{ account.name | pa pub fn fetch_{{ account.name | snakeCase }}( rpc: &solana_client::rpc_client::RpcClient, address: &solana_address::Address, -) -> Result, std::io::Error> { +) -> Result, borsh::io::Error> { let accounts = fetch_all_{{ account.name | snakeCase }}(rpc, &[*address])?; Ok(accounts[0].clone()) } @@ -143,14 +143,14 @@ pub fn fetch_{{ account.name | snakeCase }}( pub fn fetch_all_{{ account.name | snakeCase }}( rpc: &solana_client::rpc_client::RpcClient, addresses: &[solana_address::Address], -) -> Result>, std::io::Error> { +) -> Result>, borsh::io::Error> { let accounts = rpc.get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::other(e.to_string()))?; - let mut decoded_accounts: Vec> = Vec::new(); + .map_err(|e| borsh::io::Error::other(alloc::format!("{e}")))?; + let mut decoded_accounts: alloc::vec::Vec> = alloc::vec::Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; let account = accounts[i].as_ref() - .ok_or(std::io::Error::other(format!("Account not found: {address}")))?; + .ok_or(borsh::io::Error::other(alloc::format!("Account not found: {address}")))?; let data = {{ account.name | pascalCase }}::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, account: account.clone(), data }); } @@ -161,7 +161,7 @@ pub fn fetch_all_{{ account.name | snakeCase }}( pub fn fetch_maybe_{{ account.name | snakeCase }}( rpc: &solana_client::rpc_client::RpcClient, address: &solana_address::Address, -) -> Result, std::io::Error> { +) -> Result, borsh::io::Error> { let accounts = fetch_all_maybe_{{ account.name | snakeCase }}(rpc, &[*address])?; Ok(accounts[0].clone()) } @@ -170,10 +170,10 @@ pub fn fetch_maybe_{{ account.name | snakeCase }}( pub fn fetch_all_maybe_{{ account.name | snakeCase }}( rpc: &solana_client::rpc_client::RpcClient, addresses: &[solana_address::Address], -) -> Result>, std::io::Error> { +) -> Result>, borsh::io::Error> { let accounts = rpc.get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::other(e.to_string()))?; - let mut decoded_accounts: Vec> = Vec::new(); + .map_err(|e| borsh::io::Error::other(alloc::format!("{e}")))?; + let mut decoded_accounts: alloc::vec::Vec> = alloc::vec::Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { diff --git a/public/templates/instructionsPage.njk b/public/templates/instructionsPage.njk index e715676..ea26993 100644 --- a/public/templates/instructionsPage.njk +++ b/public/templates/instructionsPage.njk @@ -131,7 +131,7 @@ impl {{ instruction.name | pascalCase }}InstructionData { } {% if dataTraits | hasTrait('BorshSerialize', 'borsh::BorshSerialize') %} - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } {% endif %} @@ -154,7 +154,7 @@ impl Default for {{ instruction.name | pascalCase }}InstructionData { {% if dataTraits | hasTrait('BorshSerialize', 'borsh::BorshSerialize') %} impl {{ instruction.name | pascalCase }}InstructionArgs { - pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error> { borsh::to_vec(self) } } diff --git a/public/templates/rootMod.njk b/public/templates/rootMod.njk index d792bcb..c318834 100644 --- a/public/templates/rootMod.njk +++ b/public/templates/rootMod.njk @@ -2,6 +2,8 @@ {% block main %} +extern crate alloc; + {% if hasAnythingToExport %} {% if accountsToExport.length > 0 %} pub mod accounts; diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 55e65a1..e5261c5 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -150,7 +150,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { visitInstruction(node) { // Imports. - const imports = new ImportMap(); + const imports = new ImportMap().add(['alloc::boxed::Box', 'alloc::vec::Vec']); // canMergeAccountsAndArgs const accountsAndArgsConflicts = getConflictsForInstructionAccountsAndArgs(node); diff --git a/src/getTypeManifestVisitor.ts b/src/getTypeManifestVisitor.ts index 5bddf8e..ee74a18 100644 --- a/src/getTypeManifestVisitor.ts +++ b/src/getTypeManifestVisitor.ts @@ -98,6 +98,7 @@ export function getTypeManifestVisitor(options: { case 'u32': return { ...childManifest, + imports: childManifest.imports.add('alloc::vec::Vec'), type: `Vec<${childManifest.type}>`, }; case 'u8': @@ -267,10 +268,10 @@ export function getTypeManifestVisitor(options: { const key = visit(mapType.key, self); const value = visit(mapType.value, self); const mergedManifest = mergeManifests([key, value]); - mergedManifest.imports.add('std::collections::HashMap'); + mergedManifest.imports.add('alloc::collections::BTreeMap'); return { ...mergedManifest, - type: `HashMap<${key.type}, ${value.type}>`, + type: `BTreeMap<${key.type}, ${value.type}>`, }; }, @@ -324,10 +325,10 @@ export function getTypeManifestVisitor(options: { visitSetType(setType, { self }) { const childManifest = visit(setType.item, self); - childManifest.imports.add('std::collections::HashSet'); + childManifest.imports.add('alloc::collections::BTreeSet'); return { ...childManifest, - type: `HashSet<${childManifest.type}>`, + type: `BTreeSet<${childManifest.type}>`, }; }, @@ -359,7 +360,7 @@ export function getTypeManifestVisitor(options: { switch (parentSize.format) { case 'u32': return { - imports: new ImportMap(), + imports: new ImportMap().add('alloc::string::String'), nestedStructs: [], type: 'String', }; diff --git a/src/renderValueNodeVisitor.ts b/src/renderValueNodeVisitor.ts index f48af80..a26704d 100644 --- a/src/renderValueNodeVisitor.ts +++ b/src/renderValueNodeVisitor.ts @@ -94,10 +94,10 @@ export function renderValueNodeVisitor( }, visitMapValue(node) { const map = node.entries.map(entry => visit(entry, this)); - const imports = new ImportMap().add('std::collection::HashMap'); + const imports = new ImportMap().add('alloc::collections::BTreeMap'); return { imports: imports.mergeWith(...map.map(c => c.imports)), - render: `HashMap::from([${map.map(c => c.render).join(', ')}])`, + render: `BTreeMap::from([${map.map(c => c.render).join(', ')}])`, }; }, visitNoneValue() { @@ -120,10 +120,10 @@ export function renderValueNodeVisitor( }, visitSetValue(node) { const set = node.items.map(v => visit(v, this)); - const imports = new ImportMap().add('std::collection::HashSet'); + const imports = new ImportMap().add('alloc::collections::BTreeSet'); return { imports: imports.mergeWith(...set.map(c => c.imports)), - render: `HashSet::from([${set.map(c => c.render).join(', ')}])`, + render: `BTreeSet::from([${set.map(c => c.render).join(', ')}])`, }; }, visitSomeValue(node) { @@ -136,7 +136,9 @@ export function renderValueNodeVisitor( visitStringValue(node) { return { imports: new ImportMap(), - render: useStr ? `${JSON.stringify(node.string)}` : `String::from(${JSON.stringify(node.string)})`, + render: useStr + ? `${JSON.stringify(node.string)}` + : `alloc::string::String::from(${JSON.stringify(node.string)})`, }; }, visitStructFieldValue(node) { diff --git a/src/renderVisitor.ts b/src/renderVisitor.ts index caf8481..59d7b8d 100644 --- a/src/renderVisitor.ts +++ b/src/renderVisitor.ts @@ -5,6 +5,7 @@ import { spawnSync } from 'child_process'; import { GetRenderMapOptions, getRenderMapVisitor } from './getRenderMapVisitor'; import { syncCargoToml } from './utils'; +import { assertNoStdCompatible } from './utils/noStd'; export type RenderOptions = GetRenderMapOptions & { deleteFolderBeforeRendering?: boolean; @@ -25,6 +26,7 @@ export function renderVisitor(crateFolder: string, options: RenderOptions = {}) // Render the new files. const renderMap = visit(root, getRenderMapVisitor(options)); + assertNoStdCompatible(renderMap); writeRenderMap(renderMap, generatedFolder); // Sync Cargo.toml dependencies and versions, if requested. diff --git a/src/utils/cargoToml.ts b/src/utils/cargoToml.ts index a7da14a..3124828 100644 --- a/src/utils/cargoToml.ts +++ b/src/utils/cargoToml.ts @@ -41,19 +41,19 @@ type CargoDependencyObject = { export const DEFAULT_DEPENDENCY_VERSIONS: CargoDependencies = { 'anchor-lang': { optional: true, version: '~0.31' }, - borsh: '^1.0', + borsh: { 'default-features': false, features: ['derive'], version: '^1.0' }, 'num-derive': '^0.4', - 'num-traits': '^0.2', + 'num-traits': { 'default-features': false, version: '^0.2' }, 'solana-account': '~3.0', 'solana-account-info': '~3.1', 'solana-address': { features: ['borsh', 'copy', 'curve25519', 'decode'], version: '~2.2' }, 'solana-client': { optional: true, version: '^3.0' }, 'solana-cpi': '~3.1', 'solana-decode-error': '~2.3', - 'solana-instruction': '~3.2', + 'solana-instruction': { 'default-features': false, version: '~3.2' }, 'solana-program-error': '~3.0', 'spl-collections': { features: ['borsh'], version: '^0.1' }, - thiserror: '^1.0', + thiserror: { 'default-features': false, version: '^2.0' }, }; export function syncCargoToml( diff --git a/src/utils/index.ts b/src/utils/index.ts index 6e73eb3..e585ce3 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,5 +3,6 @@ export * from './codecs'; export * from './discriminatorConstant'; export * from './fragment'; export * from './linkOverrides'; +export * from './noStd'; export * from './render'; export * from './traitOptions'; diff --git a/src/utils/noStd.ts b/src/utils/noStd.ts new file mode 100644 index 0000000..0577fdc --- /dev/null +++ b/src/utils/noStd.ts @@ -0,0 +1,23 @@ +import type { RenderMap } from '@codama/renderers-core'; + +import type { Fragment } from './fragment'; + +const STD_REFERENCE_PATTERN = /\bstd::/; + +export function assertNoStdCompatible(renderMap: RenderMap): void { + const offenders = [...renderMap.entries()].flatMap(([filePath, fragment]) => { + return fragment.content + .split('\n') + .map((line, index) => ({ filePath, line, lineNumber: index + 1 })) + .filter(({ line }) => STD_REFERENCE_PATTERN.test(line)); + }); + + if (offenders.length === 0) { + return; + } + + const details = offenders + .map(({ filePath, line, lineNumber }) => `- ${filePath}:${lineNumber}: ${line.trim()}`) + .join('\n'); + throw new Error(`[Rust] Generated output is not no_std-compatible.\n${details}`); +} diff --git a/src/utils/traitOptions.ts b/src/utils/traitOptions.ts index da98dd9..1e77fbe 100644 --- a/src/utils/traitOptions.ts +++ b/src/utils/traitOptions.ts @@ -42,7 +42,7 @@ export const DEFAULT_TRAIT_OPTIONS: Required = { dataEnumDefaults: [], featureFlags: {}, overrides: {}, - scalarEnumDefaults: ['Copy', 'PartialOrd', 'Hash', 'num_derive::FromPrimitive'], + scalarEnumDefaults: ['Copy', 'PartialOrd', 'Ord', 'Hash', 'num_derive::FromPrimitive'], structDefaults: [], useFullyQualifiedName: false, }; diff --git a/test/utils/noStd.test.ts b/test/utils/noStd.test.ts new file mode 100644 index 0000000..408cd12 --- /dev/null +++ b/test/utils/noStd.test.ts @@ -0,0 +1,30 @@ +import { createRenderMap } from '@codama/renderers-core'; +import { describe, expect, test } from 'vitest'; + +import { ImportMap } from '../../src'; +import { assertNoStdCompatible, Fragment } from '../../src/utils'; + +function fragment(content: string): Fragment { + return { + content, + imports: new ImportMap(), + }; +} + +describe('assertNoStdCompatible', () => { + test('it accepts alloc-only output', () => { + const renderMap = createRenderMap({ + 'lib.rs': fragment('use alloc::vec::Vec;\nextern crate alloc;\n'), + }); + + expect(() => assertNoStdCompatible(renderMap)).not.toThrow(); + }); + + test('it rejects generated std references', () => { + const renderMap = createRenderMap({ + 'lib.rs': fragment('use std::vec::Vec;\n'), + }); + + expect(() => assertNoStdCompatible(renderMap)).toThrow('[Rust] Generated output is not no_std-compatible.'); + }); +}); diff --git a/test/utils/traitOptions.test.ts b/test/utils/traitOptions.test.ts index 5609923..a90d38d 100644 --- a/test/utils/traitOptions.test.ts +++ b/test/utils/traitOptions.test.ts @@ -61,7 +61,7 @@ describe('default values', () => { // Then we expect the following traits to be rendered. expect(render).toBe( - `#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, Copy, PartialOrd, Hash, FromPrimitive)]\n`, + `#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, Copy, PartialOrd, Ord, Hash, FromPrimitive)]\n`, ); // And the following imports to be used. @@ -378,7 +378,7 @@ describe('conditional try_to_vec generation', () => { // Then we expect the try_to_vec method to be included with borsh::to_vec implementation. const instruction = getFromRenderMap(renderMap, 'instructions/transfer.rs').content; - expect(instruction).toContain('pub(crate) fn try_to_vec(&self) -> Result, std::io::Error>'); + expect(instruction).toContain('pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error>'); expect(instruction).toContain('borsh::to_vec(self)'); // And the instruction functions should use try_to_vec. @@ -450,7 +450,7 @@ describe('conditional try_to_vec generation', () => { // Then we expect try_to_vec to be generated even with fully qualified trait name. const instruction = getFromRenderMap(renderMap, 'instructions/transfer.rs').content; - expect(instruction).toContain('pub(crate) fn try_to_vec(&self) -> Result, std::io::Error>'); + expect(instruction).toContain('pub(crate) fn try_to_vec(&self) -> Result, borsh::io::Error>'); expect(instruction).toContain('borsh::to_vec(self)'); expect(instruction).toContain('#[derive(borsh::BorshSerialize'); });