-
Notifications
You must be signed in to change notification settings - Fork 60
interface: Split out instructions, state, errors from program #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
rustopian
merged 10 commits into
solana-program:main
from
rustopian:split-spl-token-interface
Aug 4, 2025
Merged
Changes from 8 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
0c8788e
split out spl-token-interface
rustopian 731de46
rm now unused dev deps
rustopian fe10fff
try purge
rustopian 3126dc2
try purge
rustopian b4e6c19
fix deps, add interface test, re-exports
rustopian 81741bf
fmt and align deps
rustopian a3d1bd4
clear unneeded lockfile update
rustopian 345d022
fmt
rustopian b15ca15
interface:test
rustopian 8f03ff2
better title for step
rustopian File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
[package] | ||
name = "spl-token-interface" | ||
version = "1.0.0" | ||
description = "Solana Program Library Token Interface" | ||
documentation = "https://docs.rs/spl-token-interface" | ||
readme = "README.md" | ||
authors = { workspace = true } | ||
repository = { workspace = true } | ||
license = { workspace = true } | ||
edition = { workspace = true } | ||
|
||
[dependencies] | ||
arrayref = "0.3.9" | ||
bytemuck = "1.20.0" | ||
num-derive = "0.4" | ||
num_enum = "0.7.4" | ||
num-traits = "0.2" | ||
solana-instruction = "2.3.0" | ||
solana-program-error = "2.2.2" | ||
solana-program-option = "2.2.1" | ||
solana-program-pack = "2.2.1" | ||
solana-pubkey = { version = "2.4.0", features = ["bytemuck"] } | ||
solana-sdk-ids = "2.2.1" | ||
thiserror = "2.0" | ||
|
||
[dev-dependencies] | ||
proptest = "1.5" | ||
strum = "0.24" | ||
strum_macros = "0.24" | ||
|
||
[lib] | ||
crate-type = ["lib"] | ||
|
||
[package.metadata.docs.rs] | ||
targets = ["x86_64-unknown-linux-gnu"] | ||
|
||
[lints] | ||
workspace = true | ||
|
||
[package.metadata.solana] | ||
program-id = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Token Interface | ||
|
||
A token program interface on the Solana blockchain, usable for fungible and | ||
non-fungible tokens. | ||
|
||
This crate provides an interface that third parties can utilize to create and | ||
use their tokens. | ||
|
||
Full documentation is available at [https://www.solana-program.com/docs/token](https://www.solana-program.com/docs/token) | ||
|
||
## Audit | ||
|
||
The audit repository [README](https://github.com/solana-labs/solana-program-library#audits) | ||
contains information about program audits. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
//! Error types | ||
|
||
use { | ||
num_derive::FromPrimitive, | ||
solana_program_error::{ProgramError, ToStr}, | ||
thiserror::Error, | ||
}; | ||
|
||
/// Errors that may be returned by the Token program. | ||
#[cfg_attr(test, derive(strum_macros::FromRepr, strum_macros::EnumIter))] | ||
#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)] | ||
pub enum TokenError { | ||
// 0 | ||
/// Lamport balance below rent-exempt threshold. | ||
#[error("Lamport balance below rent-exempt threshold")] | ||
NotRentExempt, | ||
/// Insufficient funds for the operation requested. | ||
#[error("Insufficient funds")] | ||
InsufficientFunds, | ||
/// Invalid Mint. | ||
#[error("Invalid Mint")] | ||
InvalidMint, | ||
/// Account not associated with this Mint. | ||
#[error("Account not associated with this Mint")] | ||
MintMismatch, | ||
/// Owner does not match. | ||
#[error("Owner does not match")] | ||
OwnerMismatch, | ||
|
||
// 5 | ||
/// This token's supply is fixed and new tokens cannot be minted. | ||
#[error("Fixed supply")] | ||
FixedSupply, | ||
/// The account cannot be initialized because it is already being used. | ||
#[error("Already in use")] | ||
AlreadyInUse, | ||
/// Invalid number of provided signers. | ||
#[error("Invalid number of provided signers")] | ||
InvalidNumberOfProvidedSigners, | ||
/// Invalid number of required signers. | ||
#[error("Invalid number of required signers")] | ||
InvalidNumberOfRequiredSigners, | ||
/// State is uninitialized. | ||
#[error("State is uninitialized")] | ||
UninitializedState, | ||
|
||
// 10 | ||
/// Instruction does not support native tokens | ||
#[error("Instruction does not support native tokens")] | ||
NativeNotSupported, | ||
/// Non-native account can only be closed if its balance is zero | ||
#[error("Non-native account can only be closed if its balance is zero")] | ||
NonNativeHasBalance, | ||
/// Invalid instruction | ||
#[error("Invalid instruction")] | ||
InvalidInstruction, | ||
/// State is invalid for requested operation. | ||
#[error("State is invalid for requested operation")] | ||
InvalidState, | ||
/// Operation overflowed | ||
#[error("Operation overflowed")] | ||
Overflow, | ||
|
||
// 15 | ||
/// Account does not support specified authority type. | ||
#[error("Account does not support specified authority type")] | ||
AuthorityTypeNotSupported, | ||
/// This token mint cannot freeze accounts. | ||
#[error("This token mint cannot freeze accounts")] | ||
MintCannotFreeze, | ||
/// Account is frozen; all account operations will fail | ||
#[error("Account is frozen")] | ||
AccountFrozen, | ||
/// Mint decimals mismatch between the client and mint | ||
#[error("The provided decimals value different from the Mint decimals")] | ||
MintDecimalsMismatch, | ||
/// Instruction does not support non-native tokens | ||
#[error("Instruction does not support non-native tokens")] | ||
NonNativeNotSupported, | ||
} | ||
impl From<TokenError> for ProgramError { | ||
fn from(e: TokenError) -> Self { | ||
ProgramError::Custom(e as u32) | ||
} | ||
} | ||
|
||
impl TryFrom<u32> for TokenError { | ||
type Error = ProgramError; | ||
fn try_from(error: u32) -> Result<Self, Self::Error> { | ||
match error { | ||
0 => Ok(TokenError::NotRentExempt), | ||
1 => Ok(TokenError::InsufficientFunds), | ||
2 => Ok(TokenError::InvalidMint), | ||
3 => Ok(TokenError::MintMismatch), | ||
4 => Ok(TokenError::OwnerMismatch), | ||
5 => Ok(TokenError::FixedSupply), | ||
6 => Ok(TokenError::AlreadyInUse), | ||
7 => Ok(TokenError::InvalidNumberOfProvidedSigners), | ||
8 => Ok(TokenError::InvalidNumberOfRequiredSigners), | ||
9 => Ok(TokenError::UninitializedState), | ||
10 => Ok(TokenError::NativeNotSupported), | ||
11 => Ok(TokenError::NonNativeHasBalance), | ||
12 => Ok(TokenError::InvalidInstruction), | ||
13 => Ok(TokenError::InvalidState), | ||
14 => Ok(TokenError::Overflow), | ||
15 => Ok(TokenError::AuthorityTypeNotSupported), | ||
16 => Ok(TokenError::MintCannotFreeze), | ||
17 => Ok(TokenError::AccountFrozen), | ||
18 => Ok(TokenError::MintDecimalsMismatch), | ||
19 => Ok(TokenError::NonNativeNotSupported), | ||
_ => Err(ProgramError::InvalidArgument), | ||
} | ||
} | ||
} | ||
|
||
impl ToStr for TokenError { | ||
fn to_str<E>(&self) -> &'static str { | ||
match self { | ||
TokenError::NotRentExempt => "Error: Lamport balance below rent-exempt threshold", | ||
TokenError::InsufficientFunds => "Error: insufficient funds", | ||
TokenError::InvalidMint => "Error: Invalid Mint", | ||
TokenError::MintMismatch => "Error: Account not associated with this Mint", | ||
TokenError::OwnerMismatch => "Error: owner does not match", | ||
TokenError::FixedSupply => "Error: the total supply of this token is fixed", | ||
TokenError::AlreadyInUse => "Error: account or token already in use", | ||
TokenError::InvalidNumberOfProvidedSigners => { | ||
"Error: Invalid number of provided signers" | ||
} | ||
TokenError::InvalidNumberOfRequiredSigners => { | ||
"Error: Invalid number of required signers" | ||
} | ||
TokenError::UninitializedState => "Error: State is uninitialized", | ||
TokenError::NativeNotSupported => "Error: Instruction does not support native tokens", | ||
TokenError::NonNativeHasBalance => { | ||
"Error: Non-native account can only be closed if its balance is zero" | ||
} | ||
TokenError::InvalidInstruction => "Error: Invalid instruction", | ||
TokenError::InvalidState => "Error: Invalid account state for operation", | ||
TokenError::Overflow => "Error: Operation overflowed", | ||
TokenError::AuthorityTypeNotSupported => { | ||
"Error: Account does not support specified authority type" | ||
} | ||
TokenError::MintCannotFreeze => "Error: This token mint cannot freeze accounts", | ||
TokenError::AccountFrozen => "Error: Account is frozen", | ||
TokenError::MintDecimalsMismatch => "Error: decimals different from the Mint decimals", | ||
TokenError::NonNativeNotSupported => { | ||
"Error: Instruction does not support non-native tokens" | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use {super::*, strum::IntoEnumIterator}; | ||
#[test] | ||
fn test_parse_error_from_primitive_exhaustive() { | ||
for variant in TokenError::iter() { | ||
let variant_u32 = variant as u32; | ||
assert_eq!( | ||
TokenError::from_repr(variant_u32 as usize).unwrap(), | ||
TokenError::try_from(variant_u32).unwrap() | ||
); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.