[license](https://github.com/rtrombone/safer-solana/blob/main/LICENSE) [crates.io](https://crates.io/crates/sealevel-tools) [docs.rs](https://docs.rs/sealevel-tools) # Sealevel Tools Tools for safer Solana development. This crate is not an attempt to create a new framework for writing Solana programs. Instead, it is a set of tools that should help a developer write a Solana program without prescribing any specific way of doing so. By using these tools, a developer can write a lightweight program with functionality found in other frameworks. See crate [documentation] for more information. ## Dependencies **Minimum-supported Rust version: 1.75.** Currently, this package only supports Solana version ^1.18 to match Solana dependencies found in [solana-nostd-entrypoint], meaning that **this package does not yet support Solana 2.0**. ## Feature Flags When you add this package, the following features are enabled by default: ```toml default = [ "alloc", "borsh", "token" ] ``` To disable these defaults (e.g. using a heapless environment via [noalloc_allocator]), use `default-features = false` in your Cargo.toml and add the features you need for your program: ```toml sealevel-tools = { version = "0.4.0", default-features = false, features = ["noalloc-default"] } ``` ### `features = ["alloc"]` Using the Rust's core allocation library, enable this feature. If this feature is disabled, be aware that error resolution decreases. For example, with alloc on, you may encounter a program log resembling: ```console Program log: Custom error: AccountInfo Program log: Account key mismatch at index 1... Program log: Found: 7UbHLbKLfvh3maXuCZMWqKjzMCeLczaJwWTSLVpYV38z Program log: Expected: CjasN94JjDrDeZkxenJGNrN1sqBeHauNkJDp48VQdrtm ``` **NOTE: With the above example, any referenced index is based on zero-indexed account enumeration.** And without it, the same error would produce: ```console Program log: Custom error: AccountInfo Program log: Account does not match expected key ``` Having no allocator is extreme. You can still write a program that does not allocate to the heap and keep this feature enabled so that the program logs have more colorful error messages. There would only be a cost to process these errors if preflight were skipped when sending the transaction and you wanted these failed transactions to persist on-chain. See [alloc] documentation for more information. ### `features = ["borsh"]` Account handling relating to [borsh] serialization. It is up to you to determine whether there is too much overhead to use this serialization library and whether it is worth the time to write your own serde. It should be no cost to have this feature enabled. And as an integrator with another program, you will have the option to deserialize accounts of programs written with frameworks like [anchor-lang]. ### `features = ["token"]` Account and CPI handling relating to the SPL Token programs (legacy and Extensions). There are convenient methods that create mints and token accounts, which basically pair a System program's create account with an initialize mint or initialize token account instruction to allow these operations to happen atomically in your program's instruction (as opposed to having to create an account in an instruction prior to invoking your program's). ## Philosophy The tools found in this crate are meant to allow a developer to keep things as simple as possible while providing some guardrails. These guardrails are not meant to enforce any specific way of iterating through entrypoint accounts, account serialization/deserialization (serde), how instruction discriminators should be set, etc. The developer should write a program without any artificial constraints. For example, a developer may want instruction selectors to be the first 4-bytes of a Keccak256 hash similar to how Solidity for EVM works. Or to be consistent with how [anchor-lang] and [spl-discriminator] define discriminators as the first 8-bytes of Sha256 (sha2). What this crate does not attempt to do is generate an IDL. While convenient when using frameworks like [anchor-lang] and [shank] (where a front-end language-agnostic developer can take an IDL and build an SDK using it), these tools are meant to focus on safer program development. Writing instruction builders is trivial, and any time spent trying to resolve headaches having an IDL build using any of these frameworks can be saved by writing custom instruction builders in whichever language you want to support. Solana program frameworks attempt to remove boilerplate from writing instruction processors. But with that comes the price of having to learn how these specific macros work. And these macros can add a lot of bloat to your program, where your program size can easily be double the size of a program with the same logic but without a specific framework. [alloc]: https://doc.rust-lang.org/alloc/ [anchor-lang]: https://docs.rs/anchor-lang/ [borsh]: https://docs.rs/borsh/ [documentation]: https://docs.rs/sealevel-tools/ [noalloc_allocator]: https://docs.rs/solana-nostd-entrypoint/0.5.1/solana_nostd_entrypoint/macro.noalloc_allocator.html [solana-nostd-entrypoint]: https://docs.rs/solana-nostd-entrypoint/ [spl-discriminator]: https://docs.rs/spl-discriminator/ [shank]: https://docs.rs/shank/