From cb4b9696eeb9f4b2427900f0f9a88834813f8dc8 Mon Sep 17 00:00:00 2001 From: Eric Alaribe <42889673+funkycadet@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:51:52 +0100 Subject: [PATCH] add tokens/create-token/steel (#299) --- tokens/create-token/steel/.gitignore | 2 + tokens/create-token/steel/Cargo.toml | 21 +++++++++ tokens/create-token/steel/README.md | 22 +++++++++ tokens/create-token/steel/api/Cargo.toml | 13 ++++++ tokens/create-token/steel/api/src/consts.rs | 8 ++++ tokens/create-token/steel/api/src/error.rs | 10 +++++ .../create-token/steel/api/src/instruction.rs | 17 +++++++ tokens/create-token/steel/api/src/lib.rs | 16 +++++++ tokens/create-token/steel/api/src/sdk.rs | 27 +++++++++++ tokens/create-token/steel/program/Cargo.toml | 19 ++++++++ tokens/create-token/steel/program/src/lib.rs | 21 +++++++++ .../create-token/steel/program/src/token.rs | 35 +++++++++++++++ .../create-token/steel/program/tests/test.rs | 45 +++++++++++++++++++ 13 files changed, 256 insertions(+) create mode 100644 tokens/create-token/steel/.gitignore create mode 100644 tokens/create-token/steel/Cargo.toml create mode 100644 tokens/create-token/steel/README.md create mode 100644 tokens/create-token/steel/api/Cargo.toml create mode 100644 tokens/create-token/steel/api/src/consts.rs create mode 100644 tokens/create-token/steel/api/src/error.rs create mode 100644 tokens/create-token/steel/api/src/instruction.rs create mode 100644 tokens/create-token/steel/api/src/lib.rs create mode 100644 tokens/create-token/steel/api/src/sdk.rs create mode 100644 tokens/create-token/steel/program/Cargo.toml create mode 100644 tokens/create-token/steel/program/src/lib.rs create mode 100644 tokens/create-token/steel/program/src/token.rs create mode 100644 tokens/create-token/steel/program/tests/test.rs diff --git a/tokens/create-token/steel/.gitignore b/tokens/create-token/steel/.gitignore new file mode 100644 index 000000000..052739dbc --- /dev/null +++ b/tokens/create-token/steel/.gitignore @@ -0,0 +1,2 @@ +target +test-ledger diff --git a/tokens/create-token/steel/Cargo.toml b/tokens/create-token/steel/Cargo.toml new file mode 100644 index 000000000..203056488 --- /dev/null +++ b/tokens/create-token/steel/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +resolver = "2" +members = ["api", "program"] + +[workspace.package] +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +homepage = "" +documentation = "" +respository = "" +readme = "./README.md" +keywords = ["solana"] + +[workspace.dependencies] +steel-api = { path = "./api", version = "0.1.0" } +bytemuck = "1.14" +num_enum = "0.7" +solana-program = "1.18" +steel = "1.3" +thiserror = "1.0" diff --git a/tokens/create-token/steel/README.md b/tokens/create-token/steel/README.md new file mode 100644 index 000000000..4f4fe2a54 --- /dev/null +++ b/tokens/create-token/steel/README.md @@ -0,0 +1,22 @@ +# Steel + +**Steel** is a ... + +## API +- [`Consts`](api/src/consts.rs) – Program constants. +- [`Error`](api/src/error.rs) – Custom program errors. +- [`Event`](api/src/event.rs) – Custom program events. +- [`Instruction`](api/src/instruction.rs) – Declared instructions. + +## Instructions +- [`Hello`](program/src/hello.rs) – Hello ... + +## State +- [`User`](api/src/state/user.rs) – User ... + +## Tests + +To run the test suit, use the Solana toolchain: +``` +cargo test-sbf +``` diff --git a/tokens/create-token/steel/api/Cargo.toml b/tokens/create-token/steel/api/Cargo.toml new file mode 100644 index 000000000..fa3a06698 --- /dev/null +++ b/tokens/create-token/steel/api/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "steel-api" +version = "0.1.0" +edition = "2021" + +[dependencies] +bytemuck.workspace = true +num_enum.workspace = true +solana-program.workspace = true +spl-token = "6.0.0" +steel.workspace = true +steel-program = { version = "0.1.0", path = "../program" } +thiserror.workspace = true diff --git a/tokens/create-token/steel/api/src/consts.rs b/tokens/create-token/steel/api/src/consts.rs new file mode 100644 index 000000000..b6ba3c47c --- /dev/null +++ b/tokens/create-token/steel/api/src/consts.rs @@ -0,0 +1,8 @@ +/// Seed of the counter account PDA. +pub const MINT: &[u8] = b"mint"; + +pub const MINT_NOISE: [u8; 16] = [ + 89, 157, 88, 232, 243, 249, 197, 132, 199, 49, 19, 234, 91, 94, 150, 41, +]; + +pub const METADATA: &[u8] = b"metadata"; 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..96e84da4d --- /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("This is a dummy error")] + Dummy = 0, +} + +error!(SteelError); diff --git a/tokens/create-token/steel/api/src/instruction.rs b/tokens/create-token/steel/api/src/instruction.rs new file mode 100644 index 000000000..5bae066c0 --- /dev/null +++ b/tokens/create-token/steel/api/src/instruction.rs @@ -0,0 +1,17 @@ +use steel::*; + +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)] +pub enum SteelInstruction { + Create_Token = 0, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +pub struct Create_Token { + pub token_name: [u8; 32], + pub token_symbol: [u8; 8], + pub token_uri: [u8; 64], +} + +instruction!(SteelInstruction, Create_Token); diff --git a/tokens/create-token/steel/api/src/lib.rs b/tokens/create-token/steel/api/src/lib.rs new file mode 100644 index 000000000..25c5c8be6 --- /dev/null +++ b/tokens/create-token/steel/api/src/lib.rs @@ -0,0 +1,16 @@ +pub mod consts; +pub mod error; +pub mod instruction; +pub mod sdk; + +pub mod prelude { + pub use crate::consts::*; + pub use crate::error::*; + pub use crate::instruction::*; + pub use crate::sdk::*; +} + +use steel::*; + +// TODO Set program id +declare_id!("z7msBPQHDJjTvdQRoEcKyENgXDhSRYeHieN1ZMTqo35"); diff --git a/tokens/create-token/steel/api/src/sdk.rs b/tokens/create-token/steel/api/src/sdk.rs new file mode 100644 index 000000000..0ca107606 --- /dev/null +++ b/tokens/create-token/steel/api/src/sdk.rs @@ -0,0 +1,27 @@ +use steel::*; + +use crate::prelude::*; + +pub fn create_token( + payer: PubKey, + mint_authority: PubKey, + token_name: String, + token_symbol: String, + token_uri: String, +) -> Instruction { + let token_name: [u8; 32] = token_name + .as_bytes() + .try_into() + .expect("token_name must be 32 bytes"); + let token_symbol: [u8; 8] = token_symbol + .as_bytes() + .try_into() + .expect("token_symbol must be 32 bytes"); + let token_uri: [u8; 64] = token_uri + .as_bytes() + .try_into() + .expect("token_uri must be 32 bytes"); + + let mint_pda = PubKey::find_program_address(&[b"mint"], &crate::ID); + let metadata_pda = PubKey::find_program_address(); +} diff --git a/tokens/create-token/steel/program/Cargo.toml b/tokens/create-token/steel/program/Cargo.toml new file mode 100644 index 000000000..96364fed9 --- /dev/null +++ b/tokens/create-token/steel/program/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "steel-program" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +steel-api.workspace = true +solana-program.workspace = true +steel.workspace = true + +[dev-dependencies] +bs64 = "0.1.2" +rand = "0.8.5" +solana-program-test = "1.18" +solana-sdk = "1.18" +tokio = { version = "1.35", features = ["full"] } diff --git a/tokens/create-token/steel/program/src/lib.rs b/tokens/create-token/steel/program/src/lib.rs new file mode 100644 index 000000000..1804c0e85 --- /dev/null +++ b/tokens/create-token/steel/program/src/lib.rs @@ -0,0 +1,21 @@ +mod token; + +use steel::*; +use steel_api::prelude::*; +use token::*; + +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + data: &[u8], +) -> ProgramResult { + let (ix, data) = parse_instruction(&steel_api::ID, program_id, data)?; + + match ix { + SteelInstruction::Create_Token => process_create_token(accounts, name, symbol)?, + } + + Ok(()) +} + +entrypoint!(process_instruction); diff --git a/tokens/create-token/steel/program/src/token.rs b/tokens/create-token/steel/program/src/token.rs new file mode 100644 index 000000000..1b1ceb43b --- /dev/null +++ b/tokens/create-token/steel/program/src/token.rs @@ -0,0 +1,35 @@ +use solana_program::{msg, program_pack::Pack}; +use spl_token::state::Mint; +use steel::*; +use steel_api::prelude::*; + +pub fn process_create_token( + accounts: &[AccountInfo], + name: String, + symbol: String, +) -> ProgramResult { + let mint = Mint { + mint_authority: COption::Some(accounts[0].key.to_owned()), + supply: 0, + decimals: 2, + is_initialized: false, + freeze_authority: COption::None, + }; + + let mut data = vec![]; + mint.pack_into_slice(&mut data); + + let mut instruction = Instruction::new( + accounts[0].key.to_owned(), + vec![], + vec![AccountMeta::new_readonly(accounts[0].key.to_owned(), false)], + data, + ); + + let mut instruction_data = vec![]; + instruction.pack_into_slice(&mut instruction_data); + + msg!("Instruction data: {:?}", instruction_data); + + Ok(()) +} diff --git a/tokens/create-token/steel/program/tests/test.rs b/tokens/create-token/steel/program/tests/test.rs new file mode 100644 index 000000000..9a190c580 --- /dev/null +++ b/tokens/create-token/steel/program/tests/test.rs @@ -0,0 +1,45 @@ +use solana_program::hash::Hash; +use solana_program_test::{processor, BanksClient, ProgramTest}; +use solana_sdk::{signature::Keypair, signer::Signer, transaction::Transaction}; +use steel::*; +use steel_api::prelude::*; + +async fn setup() -> (BanksClient, Keypair, Hash) { + let mut program_test = ProgramTest::new( + "steel", + steel_api::ID, + processor!(steel_program::process_instruction), + ); + program_test.prefer_bpf(true); + program_test.start().await +} + +#[tokio::test] +async fn run_test() { + // Setup test + let (mut banks, payer, blockhash) = setup().await; + + // Submit initialize transaction. + let ix = initialize(payer.pubkey()); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_ok()); + + // Verify counter was initialized. + let counter_address = counter_pda().0; + let counter_account = banks.get_account(counter_address).await.unwrap().unwrap(); + let counter = Counter::try_from_bytes(&counter_account.data).unwrap(); + assert_eq!(counter_account.owner, steel_api::ID); + assert_eq!(counter.value, 0); + + // Submit add transaction. + let ix = add(payer.pubkey(), 42); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], blockhash); + let res = banks.process_transaction(tx).await; + assert!(res.is_ok()); + + // Verify counter was incremented. + let counter_account = banks.get_account(counter_address).await.unwrap().unwrap(); + let counter = Counter::try_from_bytes(&counter_account.data).unwrap(); + assert_eq!(counter.value, 42); +}