diff --git a/tokens/create-token/steel/Cargo.toml b/tokens/create-token/steel/Cargo.toml index 88477c5f7..d294bdd12 100644 --- a/tokens/create-token/steel/Cargo.toml +++ b/tokens/create-token/steel/Cargo.toml @@ -9,3 +9,4 @@ bytemuck = "1.4" num_enum = "0.7" spl-token = { version = "4.0.0", features = [ "no-entrypoint" ] } mpl-token-metadata = { version = "4.1.2" } +thiserror = "2.0.3" \ No newline at end of file diff --git a/tokens/create-token/steel/api/Cargo.toml b/tokens/create-token/steel/api/Cargo.toml index 139cf2b43..af6f7ae35 100644 --- a/tokens/create-token/steel/api/Cargo.toml +++ b/tokens/create-token/steel/api/Cargo.toml @@ -13,3 +13,4 @@ bytemuck.workspace = true num_enum.workspace = true spl-token.workspace = true mpl-token-metadata.workspace = true +thiserror.workspace = true diff --git a/tokens/create-token/steel/api/src/error.rs b/tokens/create-token/steel/api/src/error.rs new file mode 100644 index 000000000..a3c09c76c --- /dev/null +++ b/tokens/create-token/steel/api/src/error.rs @@ -0,0 +1,10 @@ +use steel::*; + +#[derive(Debug, Error, Clone, Copy, PartialEq, Eq, IntoPrimitive)] +#[repr(u32)] +pub enum SteelError { + #[error("Failed to parse string from bytes")] + ParseError = 0, +} + +error!(SteelError); diff --git a/tokens/create-token/steel/api/src/instruction.rs b/tokens/create-token/steel/api/src/instruction.rs index 5b09203c2..ac46ec46a 100644 --- a/tokens/create-token/steel/api/src/instruction.rs +++ b/tokens/create-token/steel/api/src/instruction.rs @@ -1,5 +1,6 @@ use { - mpl_token_metadata::instructions as mpl_instruction, + crate::error::*, + mpl_token_metadata::{instructions as mpl_instruction, types::DataV2}, solana_program::{msg, program::invoke, program_pack::Pack, rent::Rent, system_instruction}, spl_token::state::Mint, std::ffi::CStr, @@ -17,9 +18,9 @@ instruction!(SteelInstruction, CreateToken); #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct CreateToken { - pub token_name: [u8; 32], - pub token_symbol: [u8; 10], - pub token_uri: [u8; 256], + pub token_name: [u8; 32], // Metaplex metadata name: 32 bytes max + pub token_symbol: [u8; 10], // Metaplex metadata symbol: 10 bytes max + pub token_uri: [u8; 256], // Metaplex metadata uri: 200 bytes max pub decimals: u8, } @@ -72,21 +73,9 @@ impl CreateToken { msg!("Creating metadata account..."); msg!("Metadata account address: {}", metadata_account.key); - let name = CStr::from_bytes_until_nul(&args.token_name) - .unwrap() - .to_str() - .unwrap() - .to_string(); - let symbol = CStr::from_bytes_until_nul(&args.token_symbol) - .unwrap() - .to_str() - .unwrap() - .to_string(); - let uri = CStr::from_bytes_until_nul(&args.token_uri) - .unwrap() - .to_str() - .unwrap() - .to_string(); + let name = Self::str_from_bytes(&mut args.token_name.to_vec())?.to_string(); + let symbol = Self::str_from_bytes(&mut args.token_symbol.to_vec())?.to_string(); + let uri = Self::str_from_bytes(&mut args.token_uri.to_vec())?.to_string(); mpl_instruction::CreateMetadataAccountV3Cpi { __program: token_metadata_program, @@ -97,8 +86,8 @@ impl CreateToken { update_authority: (mint_authority, true), system_program, rent: Some(rent), - __args: mpl_token_metadata::instructions::CreateMetadataAccountV3InstructionArgs { - data: mpl_token_metadata::types::DataV2 { + __args: mpl_instruction::CreateMetadataAccountV3InstructionArgs { + data: DataV2 { name, symbol, uri, @@ -117,4 +106,17 @@ impl CreateToken { Ok(()) } + + fn str_from_bytes(bytes: &mut Vec) -> Result<&str, ProgramError> { + // add an extra null byte, in the case every position is occupied with a non-null byte + bytes.push(0); + + // remove excess null bytes + if let Ok(cstr) = CStr::from_bytes_until_nul(bytes) { + if let Ok(str) = cstr.to_str() { + return Ok(str); + } + } + Err(SteelError::ParseError.into()) + } } diff --git a/tokens/create-token/steel/api/src/lib.rs b/tokens/create-token/steel/api/src/lib.rs index 0ee82eb65..2ae690b1d 100644 --- a/tokens/create-token/steel/api/src/lib.rs +++ b/tokens/create-token/steel/api/src/lib.rs @@ -1,6 +1,8 @@ +pub mod error; pub mod instruction; pub mod prelude { + pub use crate::error::*; pub use crate::instruction::*; }