{"id":30113951,"url":"https://github.com/near/near-sdk-contract-tools","last_synced_at":"2025-09-10T01:37:56.133Z","repository":{"id":37075404,"uuid":"490861720","full_name":"near/near-sdk-contract-tools","owner":"near","description":"Helpful functions and macros for developing smart contracts on NEAR Protocol.","archived":false,"fork":false,"pushed_at":"2025-07-16T20:19:12.000Z","size":1550,"stargazers_count":45,"open_issues_count":25,"forks_count":8,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2025-08-28T20:37:52.950Z","etag":null,"topics":["blockchain","dapp","near","nearprotocol","rust","smart-contracts","wasm","webassembly"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/near-sdk-contract-tools","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/near.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-05-10T21:11:19.000Z","updated_at":"2025-08-07T03:02:08.000Z","dependencies_parsed_at":"2023-07-14T08:55:43.612Z","dependency_job_id":"dfa85b31-1146-4961-82c3-411f8414057f","html_url":"https://github.com/near/near-sdk-contract-tools","commit_stats":{"total_commits":277,"total_committers":6,"mean_commits":"46.166666666666664","dds":"0.12274368231046928","last_synced_commit":"d3de8d8322c65d03b599ba632570963a00fbde9b"},"previous_names":["nearfoundation/near-contract-tools","near/near-sdk-contract-tools","nearfoundation/near-sdk-contract-tools"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/near/near-sdk-contract-tools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/near%2Fnear-sdk-contract-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/near%2Fnear-sdk-contract-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/near%2Fnear-sdk-contract-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/near%2Fnear-sdk-contract-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/near","download_url":"https://codeload.github.com/near/near-sdk-contract-tools/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/near%2Fnear-sdk-contract-tools/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274396736,"owners_count":25277395,"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","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["blockchain","dapp","near","nearprotocol","rust","smart-contracts","wasm","webassembly"],"created_at":"2025-08-10T07:36:44.787Z","updated_at":"2025-09-10T01:37:56.100Z","avatar_url":"https://github.com/near.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# near-sdk-contract-tools\n\n## NFT\n\n```rust\nuse near_sdk::near;\nuse near_sdk_contract_tools::nft::*;\n\n#[derive(Default, NonFungibleToken)]\n#[near(contract_state)]\npub struct MyNftContract {}\n\n#[near]\nimpl MyNftContract {\n    #[init]\n    pub fn new() -\u003e Self {\n        let mut contract = Self {};\n\n        contract.set_contract_metadata(\u0026ContractMetadata::new(\"My NFT\", \"MNFT\", None));\n\n        contract\n    }\n}\n```\n\n## FT\n\n```rust\nuse near_sdk::near;\nuse near_sdk_contract_tools::ft::*;\n\n#[derive(Default, FungibleToken)]\n#[near(contract_state)]\npub struct MyFtContract {}\n\n#[near]\nimpl MyFtContract {\n    #[init]\n    pub fn new() -\u003e Self {\n        let mut contract = Self {};\n\n        contract.set_metadata(\u0026ContractMetadata::new(\"My Fungible Token\", \"MYFT\", 24));\n\n        contract\n    }\n}\n```\n\n## What is it?\n\nThis package is a collection of common tools and patterns in NEAR smart contract development:\n\n- Storage fee management.\n- Escrow pattern and derive macro.\n- Owner pattern and derive macro.\n- Pause pattern and derive macro.\n- Role-based access control.\n- Derive macros for NEP standards:\n  - [NEP-141][nep141] (fungible token), extension [NEP-148][nep148].\n  - [NEP-145][nep145] (storage management), and integrations for the fungible token and non-fungible token standards.\n  - [NEP-171][nep171] (non-fungible token), extensions [NEP-177][nep177], [NEP-178][nep178], [NEP-181][nep181].\n  - [NEP-297][nep297] (events).\n\nNot to be confused with [`near-contract-standards`](https://crates.io/crates/near-contract-standards), which contains official implementations of standardized NEPs. This crate is intended to be a complement to `near-contract-standards`.\n\nYou can think of this collection of common tools and patterns (mostly in the form of [derive macros](https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros)) as a sort of [OpenZeppelin](https://docs.openzeppelin.com/contracts/4.x/) for NEAR.\n\nPro tip: Use the [contract wizard](https://near.org/contractwizard.near/widget/ContractWizardUI) to generate starter code for your next project.\n\n## Installation\n\n```bash\ncargo add near-sdk-contract-tools\n```\n\n## Examples\n\nSee also: [the full integration tests](tests/macros/mod.rs).\n\n### Owner\n\n```rust\nuse near_sdk::{near, AccountId, PanicOnDefault};\nuse near_sdk_contract_tools::{owner::Owner, Owner};\n\n#[derive(Owner, PanicOnDefault)]\n#[near(contract_state)]\nstruct Contract {\n    // ...\n}\n\n#[near]\nimpl Contract {\n    #[init]\n    pub fn new(owner_id: AccountId) -\u003e Self {\n        let mut contract = Self {\n            // ...\n        };\n\n        Owner::init(\u0026mut contract, \u0026owner_id);\n\n        contract\n    }\n\n    pub fn owner_only(\u0026self) {\n        Self::require_owner();\n\n        // ...\n    }\n}\n```\n\nThe `Owner` derive macro exposes the following methods to the blockchain:\n\n```rust, ignore\nfn own_get_owner(\u0026self) -\u003e Option\u003cAccountId\u003e;\nfn own_get_proposed_owner(\u0026self) -\u003e Option\u003cAccountId\u003e;\nfn own_renounce_owner(\u0026mut self);\nfn own_propose_owner(\u0026mut self, account_id: Option\u003cAccountId\u003e);\nfn own_accept_owner(\u0026mut self);\n```\n\n### Events\n\nThe `#[event]` macro can be applied to structs or enums.\n\n```rust\nuse near_sdk_contract_tools::{event, standard::nep297::Event};\n\n#[event(standard = \"nft\", version = \"1.0.0\")]\npub struct MintEvent {\n    pub owner_id: String,\n    pub token_id: String,\n}\n\nlet e = MintEvent {\n    owner_id: \"account\".to_string(),\n    token_id: \"token_1\".to_string(),\n};\n\n// Emits the event to the blockchain\ne.emit();\n```\n\n### Fungible Token\n\nTo create a contract that is compatible with the [NEP-141][nep141], [NEP-145][nep145], and [NEP-148][nep148] standards, that emits standard-compliant ([NEP-297][nep297]) events.\n\n```rust\nuse near_sdk::near;\nuse near_sdk_contract_tools::ft::*;\n\n#[derive(Default, FungibleToken)]\n#[near(contract_state)]\nstruct MyFt {}\n\n#[near]\nimpl MyFt {\n    #[init]\n    pub fn new() -\u003e Self {\n        let mut contract = Self {};\n\n        contract.set_metadata(\u0026ContractMetadata::new(\"My Fungible Token\", \"MYFT\", 24));\n\n        contract\n    }\n}\n```\n\nStandalone macros for each individual standard also exist.\n\n### Non-fungible Token\n\nUse the `NonFungibleToken` derive macro to implement [NEP-145][nep145], [NEP-171][nep171], [NEP-177][nep177], [NEP-178][nep178], and [NEP-181][nep181], with [NEP-297][nep297] events.\n\n```rust\nuse near_sdk::{near, PanicOnDefault};\nuse near_sdk_contract_tools::nft::*;\n\n#[derive(NonFungibleToken, PanicOnDefault)]\n#[near(contract_state)]\npub struct MyNft {}\n```\n\n### Macro Combinations\n\nOne may wish to combine the features of multiple macros in one contract. All of the macros are written such that they will work in a standalone manner, so this should largely work without issue. However, sometimes it may be desirable for the macros to work in _combination_ with each other. For example, to make a fungible token pausable, use the fungible token hooks to require that a contract be unpaused before making a token transfer:\n\n```rust\nuse near_sdk_contract_tools::{\n    ft::*,\n    pause::{*, hooks::Pausable},\n    Pause,\n};\nuse near_sdk::{near, PanicOnDefault};\n\n#[derive(FungibleToken, Pause, PanicOnDefault)]\n#[fungible_token(all_hooks = \"Pausable\")]\n#[near(contract_state)]\nstruct Contract {}\n```\n\n### Custom Crates\n\nIf you are a library developer, have modified a crate that one of the `near-sdk-contract-tools` macros uses (like `serde` or `near-sdk`), or are otherwise using a crate under a different name, you can specify crate names in macros like so:\n\n```rust, ignore\n#[event(\n    // ...\n    crate = \"near_sdk_contract_tools\",\n    macros = \"near_sdk_contract_tools_macros\",\n    serde = \"serde\",\n)]\n// ...\n\n#[derive(Owner)]\n#[owner(\n    // ...\n    near_sdk = \"near_sdk\",\n)]\n```\n\n## Other Tips\n\n### [Internal vs. External Methods](https://youtu.be/kJzes_UP5j0?t=2172)\n\nInternal methods are not available to be callable via the blockchain. External ones are public and can be called by other contracts.\n\n### [Pull pattern](https://youtu.be/kJzes_UP5j0?t=2213)\n\nProposing ownership (rather than transferring directly) is a generally good practice because it prevents you from accidentally transferring ownership to an account that nobody has access to, bricking the contract.\n\n### [Expand](https://youtu.be/kJzes_UP5j0?t=1790)\n\n[`cargo expand`](https://crates.io/crates/cargo-expand) will generate one huge Rust file with all of the macros have been processed:\n\n```text\ncargo install cargo-expand\ncargo expand \u003e expanded.rs\n```\n\n### [Slots](https://youtu.be/kJzes_UP5j0?t=2527)\n\nSee [`src/slot.rs`](src/slot.rs). Slots are thin wrappers over a storage key.\n\n### [`assert_one_yocto()`](https://youtu.be/kJzes_UP5j0?t=2989)\n\n`near_sdk::assert_one_yocto()` is a function that requires a full access key (by requiring a deposit of one yoctonear, the smallest possible unit of NEAR).\n\nIf a user connects their NEAR account to a dapp, the dapp will still not be able to call functions that call `assert_one_yocto()`, since function call access keys are not allowed to transfer native tokens. These function will require a signature from a full access key, usually involving a confirmation screen in the user's wallet.\n\n## Contributing\n\n### Setup\n\nRun `git config core.hooksPath hooks/` to set up commit hooks.\n\n### Build and test\n\nInstall `cargo-make` if it is not installed already:\n\n```text\ncargo install cargo-make cargo-nextest\n```\n\nRun tests:\n\n```text\ncargo nextest run\ncargo test --doc\ncd workspaces-tests\ncargo make nextest\n```\n\n## Audit\n\nVersion 1.0.0 of this library has been [audited](./documents/NEAR%20Contract%20Tools%20-%20Final%20-%2005.05.2023.pdf) by [Kudelski Security](https://www.kudelskisecurity.com/). (May 2023)\n\n## Authors\n\n- Jacob Lindahl [@sudo_build](https://twitter.com/sudo_build)\n\n---\n\n(Formerly known as [`near-contract-tools`](https://crates.io/crates/near-contract-tools).)\n\n[nep145]: https://nomicon.io/Standards/StorageManagement\n[nep141]: https://nomicon.io/Standards/Tokens/FungibleToken/Core\n[nep148]: https://nomicon.io/Standards/Tokens/FungibleToken/Metadata\n[nep171]: https://nomicon.io/Standards/NonFungibleToken/NonFungibleToken\n[nep177]: https://nomicon.io/Standards/Tokens/NonFungibleToken/Metadata\n[nep178]: https://nomicon.io/Standards/Tokens/NonFungibleToken/ApprovalManagement\n[nep181]: https://nomicon.io/Standards/Tokens/NonFungibleToken/Enumeration\n[nep297]: https://nomicon.io/Standards/EventsFormat\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnear%2Fnear-sdk-contract-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnear%2Fnear-sdk-contract-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnear%2Fnear-sdk-contract-tools/lists"}