{"id":15256342,"url":"https://github.com/regolith-labs/steel","last_synced_at":"2025-05-16T00:07:09.566Z","repository":{"id":257798361,"uuid":"862753671","full_name":"regolith-labs/steel","owner":"regolith-labs","description":"Solana smart contract framework.","archived":false,"fork":false,"pushed_at":"2025-04-02T17:36:53.000Z","size":290,"stargazers_count":220,"open_issues_count":15,"forks_count":41,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-09T21:34:20.761Z","etag":null,"topics":["solana"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/regolith-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-25T06:17:56.000Z","updated_at":"2025-05-07T22:11:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"4f1b2244-74cd-42e9-a1c3-e4e159972e5b","html_url":"https://github.com/regolith-labs/steel","commit_stats":{"total_commits":123,"total_committers":6,"mean_commits":20.5,"dds":"0.49593495934959353","last_synced_commit":"926feb61ef02544e3d9ceaa70ec0d38538d177b1"},"previous_names":["regolith-labs/ore-utils"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regolith-labs%2Fsteel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regolith-labs%2Fsteel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regolith-labs%2Fsteel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regolith-labs%2Fsteel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/regolith-labs","download_url":"https://codeload.github.com/regolith-labs/steel/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254442854,"owners_count":22071878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["solana"],"created_at":"2024-09-30T01:09:26.559Z","updated_at":"2025-05-16T00:07:04.548Z","avatar_url":"https://github.com/regolith-labs.png","language":"Rust","funding_links":[],"categories":["Developer Resources","\u003ca name=\"Rust\"\u003e\u003c/a\u003eRust","Frameworks"],"sub_categories":["Non-Anchor Program Development","Testing Environment"],"readme":"# 🏗️ Steel \n\n**Steel is a new framework for Solana smart contract development.** It provides a library of helper functions, macros, and code patterns for building safe and maintainable smart contracts on the Solana blockchain.\n\n## Notes\n\n- **Steel is under active development. All interfaces are subject to change.**\n- **This code is unaudited. Use at your own risk!**\n\n## Todos\n\n- [ ] IDL generation (tip: ask [Cursor](https://www.cursor.com/) to generate one)\n- [ ] Localnet toolchain.\n- [ ] Mainnet toolchain.\n- [x] ~~Helper functions for simple lamport transfers.~~\n- [x] ~~Helper functions to emit events (wrap sol_log_data).~~\n- [x] ~~Custom error messages on account validation checks.~~\n- [x] ~~Helper function to close AccountInfos.~~\n- [x] ~~CLI with init script.~~\n- [x] ~~Account parsers and validation.~~\n\n## Get started\n\nInstall the Steel CLI:\n```sh\ncargo install steel-cli\n```\n\nUse the `new` command to create a new project:\n```sh\nsteel new my-project\n```\n\nCompile your program using the Solana toolchain:\n```sh\nsteel build\n```\n\nTest your program using the Solana toolchain:\n```sh\nsteel test\n```\n\n## File structure\n\nWhile not strictly enforced, we recommend organizing your Solana program with the following file structure. We have found this pattern to improve code readability, separating the contract interface from its implementation. It scales well for complex contracts. \n\n```\nCargo.toml (workspace)\n⌙ api\n  ⌙ Cargo.toml\n  ⌙ src\n    ⌙ consts.rs\n    ⌙ error.rs\n    ⌙ event.rs\n    ⌙ instruction.rs\n    ⌙ lib.rs\n    ⌙ loaders.rs\n    ⌙ sdk.rs\n    ⌙ state\n      ⌙ mod.rs\n      ⌙ account_1.rs\n      ⌙ account_2.rs\n⌙ program\n  ⌙ Cargo.toml\n  ⌙ src\n    ⌙ lib.rs\n    ⌙ instruction_1.rs\n    ⌙ instruction_2.rs\n```\n\n## API\n\n### Accounts\n\nUse the `account!` macro to link account structs with a discriminator and implement basic serialization logic.\n\n```rs\nuse steel::*;\n\n#[repr(u8)]\n#[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]\npub enum MyAccount {\n    Counter = 0,\n    Profile = 1,\n}\n\n#[repr(C)]\n#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]\npub struct Counter {\n    pub value: u64,\n}\n\n#[repr(C)]\n#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]\npub struct Profile {\n    pub id: u64,\n}\n\naccount!(MyAccount, Counter);\naccount!(MyAccount, Profile);\n```\n\n### Instructions\n\nUse the `instruction!` macro to link instruction data with a discriminator and implement basic serialization logic.\n\n```rs\nuse steel::*;\n\n#[repr(u8)]\n#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]\npub enum MyInstruction {\n    Add = 0,\n    Initialize = 1,\n}\n\n#[repr(C)]\n#[derive(Clone, Copy, Debug, Pod, Zeroable)]\npub struct Add {\n    pub value: [u8; 8],\n}\n\n#[repr(C)]\n#[derive(Clone, Copy, Debug, Pod, Zeroable)]\npub struct Initialize {}\n\ninstruction!(MyInstruction, Add);\ninstruction!(MyInstruction, Initialize);\n\n```\n\n### Errors\n\nUse the `error!` macro to define custom errors.\n\n```rs\nuse steel::*;\n\n#[repr(u32)]\n#[derive(Debug, Error, Clone, Copy, PartialEq, Eq, IntoPrimitive)]\npub enum MyError {\n    #[error(\"You did something wrong\")]\n    Dummy = 0,\n}\n\nerror!(MyError);\n```\n\n### Events\n\nUse the `event!` macro to define custom events.\n\n```rs\nuse steel::*;\n\n#[repr(C)]\n#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]\npub struct MyEvent {\n    pub value: u64,\n}\n\nevent!(MyEvent);\n```\n\n## Program\n\n### Entrypoint\n\nUse the `entrypoint!` macro to streamline the program entrypoint.\n\n```rs\nmod add;\nmod initialize;\n\nuse add::*;\nuse initialize::*;\n\nuse example_api::prelude::*;\nuse steel::*;\n\npub fn process_instruction(\n    program_id: \u0026Pubkey,\n    accounts: \u0026[AccountInfo],\n    data: \u0026[u8],\n) -\u003e ProgramResult {\n    let (ix, data) = parse_instruction::\u003cMyInstruction\u003e(\u0026example_api::ID, program_id, data)?;\n\n    match ix {\n        MyInstruction::Add =\u003e process_add(accounts, data)?,\n        MyInstruction::Initialize =\u003e process_initialize(accounts, data)?,\n    }\n\n    Ok(())\n}\n\nentrypoint!(process_instruction);\n```\n\n### Validation\n\nUse chainable parsers and assertions to validate account data.\n\n```rs\nuse example_api::prelude::*;\nuse steel::*;\n\npub fn process_add(accounts: \u0026[AccountInfo\u003c'_\u003e], _data: \u0026[u8]) -\u003e ProgramResult {\n    let [signer_info, counter_info] = accounts else {\n        return Err(ProgramError::NotEnoughAccountKeys);\n    };\n\n    signer_info.is_signer()?;\n\n    let counter = counter_info\n        .as_account_mut::\u003cCounter\u003e(\u0026example_api::ID)? \n        .assert_mut(|c| c.value \u003c= 42)?;\n\n    counter.value += 1;\n\n    Ok(())\n}\n```\n\n### CPIs\n\nUse helper functions to execute common tasks like creating accounts and transferring tokens.\n\n```rs\nuse example_api::prelude::*;\nuse steel::*;\n\npub fn process_transfer(accounts: \u0026[AccountInfo\u003c'_\u003e], _data: \u0026[u8]) -\u003e ProgramResult {\n    let [signer_info, counter_info, mint_info, sender_info, receiver_info, token_program] = accounts else {\n        return Err(ProgramError::NotEnoughAccountKeys);\n    };\n\n    signer_info.is_signer()?;\n\n    counter_info\n        .as_account::\u003cCounter\u003e(\u0026example_api::ID)?\n        .assert(|c| c.value \u003e= 42)?;\n\n    mint_info.as_mint()?;\n\n    sender_info\n        .is_writable()?\n        .as_token_account()?\n        .assert(|t| t.owner == *signer_info.key)?\n        .assert(|t| t.mint == *mint_info.key)?;\n\n    receiver_info\n        .is_writable()?\n        .as_token_account()?\n        .assert(|t| t.mint == *mint_info.key)?;\n\n    token_program.is_program(\u0026spl_token::ID)?;\n\n    transfer(\n        signer_info,\n        sender_info,\n        receiver_info,\n        token_program,\n        counter.value,\n    )?;\n\n    Ok(())\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fregolith-labs%2Fsteel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fregolith-labs%2Fsteel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fregolith-labs%2Fsteel/lists"}