{"id":29176841,"url":"https://github.com/rustyneuron01/nearmint","last_synced_at":"2025-07-01T17:33:05.005Z","repository":{"id":164359333,"uuid":"525465730","full_name":"rustyneuron01/NearMint","owner":"rustyneuron01","description":null,"archived":false,"fork":false,"pushed_at":"2022-08-16T17:34:44.000Z","size":11867,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-14T07:51:44.368Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/rustyneuron01.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}},"created_at":"2022-08-16T16:46:53.000Z","updated_at":"2022-08-16T17:34:49.000Z","dependencies_parsed_at":"2024-04-12T02:15:03.891Z","dependency_job_id":"897d13e3-42b2-4329-815f-3e240342ceb9","html_url":"https://github.com/rustyneuron01/NearMint","commit_stats":null,"previous_names":["victoryfox19931116/nearmint","fcbtc1116/nearmint","toptrendev0829/nearmint","rustyneuron01/nearmint"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rustyneuron01/NearMint","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustyneuron01%2FNearMint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustyneuron01%2FNearMint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustyneuron01%2FNearMint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustyneuron01%2FNearMint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rustyneuron01","download_url":"https://codeload.github.com/rustyneuron01/NearMint/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustyneuron01%2FNearMint/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263007111,"owners_count":23398763,"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":[],"created_at":"2025-07-01T17:30:51.955Z","updated_at":"2025-07-01T17:33:04.994Z","avatar_url":"https://github.com/rustyneuron01.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"1. Create Project\nFor create the sample near project please run `npx create-near-app`.\nAt that time, set the Smart Contract Language as Rust, Frontend language as React.js.\nAfter that you can run\n`npm run deploy` - for Deploy contract\n`npm test` - for integration test\n`npm start` - for run fontend\n\nYou can see that all is working.\n\n2. Make Basic Project\n\nFirst Step :\nMake build.sh and Edit like this\n\n**************************************************\n#!/bin/bash\nset -e \u0026\u0026 RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release \u0026\u0026 mkdir -p ../out \u0026\u0026 cp target/wasm32-unknown-unknown/release/*.wasm ../out/main.wasm\n**************************************************\n\nSecond Step :\nMake Smart Contract files(\nlib.rs : Root file\ninterenal.rs : Declare about Internal Methods\nmetadata.rs : Declare about NFT Metadata Format\nmint.rs : Write Mint_NFT functions\n)\n\n``````````````````````````````````````````````````\ncontract\n├── Cargo.lock\n├── Cargo.toml\n├── README.md\n├── build.sh\n└── src\n    ├── internal.rs\n    ├── lib.rs\n    ├── metadata.rs\n    └── mint.rs\n``````````````````````````````````````````````````\n\n3. Build Smart Contract\n\n##lib.rs##\nModify Contract Struct\n**************************************************\n#[near_bindgen]\n#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]\npub struct Contract {\n    //contract owner\n    pub owner_id: AccountId,\n\n    //keeps track of all the token IDs for a given account\n    pub tokens_per_owner: LookupMap\u003cAccountId, UnorderedSet\u003cTokenId\u003e\u003e,\n\n    //keeps track of the token struct for a given token ID\n    pub tokens_by_id: LookupMap\u003cTokenId, Token\u003e,\n\n    //keeps track of the token metadata for a given token ID\n    pub token_metadata_by_id: UnorderedMap\u003cTokenId, TokenMetadata\u003e,\n\n    //keeps track of the metadata for the contract\n    pub metadata: LazyOption\u003cNFTContractMetadata\u003e,\n}\n**************************************************\n\nNext, create what's called an initialization function; you can name it new. This function needs to be invoked when you first deploy the contract. It will initialize all the contract's fields that you've defined above with default values. Don't forget to add the owner_id and metadata fields as parameters to the function, so only those can be customized.\n\nThis function will default all the collections to be empty and set the owner and metadata equal to what you pass in.\n\n**************************************************\n#[init]\npub fn new(owner_id: AccountId, metadata: NFTContractMetadata) -\u003e Self {\n    //create a variable of type Self with all the fields initialized. \n    let this = Self {\n        //Storage keys are simply the prefixes used for the collections. This helps avoid data collision\n        tokens_per_owner: LookupMap::new(StorageKey::TokensPerOwner.try_to_vec().unwrap()),\n        tokens_by_id: LookupMap::new(StorageKey::TokensById.try_to_vec().unwrap()),\n        token_metadata_by_id: UnorderedMap::new(\n            StorageKey::TokenMetadataById.try_to_vec().unwrap(),\n        ),\n        //set the owner_id field equal to the passed in owner_id. \n        owner_id,\n        metadata: LazyOption::new(\n            StorageKey::NFTContractMetadata.try_to_vec().unwrap(),\n            Some(\u0026metadata),\n        ),\n    };\n\n    //return the Contract object\n    this\n}\n**************************************************\nLet's create a function that can initialize the contract with a set of default metadata. You can call it new_default_meta and it'll only take the owner_id as a parameter.\n\n**************************************************\n#[init]\npub fn new_default_meta(owner_id: AccountId) -\u003e Self {\n    //calls the other function \"new: with some default metadata and the owner_id passed in \n    Self::new(\n        owner_id,\n        NFTContractMetadata {\n                spec: \"nft-1.0.0\".to_string(),\n                name: \"NFT Mint Contract\".to_string(),\n                symbol: \"NearSeed\".to_string(),\n                icon: None,\n                base_uri: None,\n                reference: None,\n                reference_hash: None,\n        },\n    )\n}\n**************************************************\n\n##metadata.rs##\nNow that you've defined what information to store on the contract itself and you've defined some ways to initialize the contract, you need to define what information should go in the Token, TokenMetadata, and NFTContractMetadata data types.\n\n**************************************************\n#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone)]\n#[serde(crate = \"near_sdk::serde\")]\npub struct NFTContractMetadata {\n    pub spec: String,              // required, essentially a version like \"nft-1.0.0\"\n    pub name: String,              // required, ex. \"Mosaics\"\n    pub symbol: String,            // required, ex. \"MOSAIC\"\n    pub icon: Option\u003cString\u003e,      // Data URL\n    pub base_uri: Option\u003cString\u003e, // Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs\n    pub reference: Option\u003cString\u003e, // URL to a JSON file with more info\n    pub reference_hash: Option\u003cBase64VecU8\u003e, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included.\n}\n\n#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize)]\n#[serde(crate = \"near_sdk::serde\")]\npub struct TokenMetadata {\n    pub title: Option\u003cString\u003e, // ex. \"Arch Nemesis: Mail Carrier\" or \"Parcel #5055\"\n    pub description: Option\u003cString\u003e, // free-form description\n    pub media: Option\u003cString\u003e, // URL to associated media, preferably to decentralized, content-addressed storage\n    pub media_hash: Option\u003cBase64VecU8\u003e, // Base64-encoded sha256 hash of content referenced by the `media` field. Required if `media` is included.\n    pub copies: Option\u003cu64\u003e, // number of copies of this set of metadata in existence when token was minted.\n    pub issued_at: Option\u003cu64\u003e, // When token was issued or minted, Unix epoch in milliseconds\n    pub expires_at: Option\u003cu64\u003e, // When token expires, Unix epoch in milliseconds\n    pub starts_at: Option\u003cu64\u003e, // When token starts being valid, Unix epoch in milliseconds\n    pub updated_at: Option\u003cu64\u003e, // When token was last updated, Unix epoch in milliseconds\n    pub extra: Option\u003cString\u003e, // anything extra the NFT wants to store on-chain. Can be stringified JSON.\n    pub reference: Option\u003cString\u003e, // URL to an off-chain JSON file with more info.\n    pub reference_hash: Option\u003cBase64VecU8\u003e, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included.\n}\n#[derive(BorshDeserialize, BorshSerialize)]\npub struct Token {\n    pub owner_id: AccountId,\n}\n**************************************************\n\nFor the Token struct, you'll just keep track of the owner for now.\n\n**************************************************\n#[derive(BorshDeserialize, BorshSerialize)]\npub struct Token {\n    //owner of the token\n    pub owner_id: AccountId,\n}\n**************************************************\n\nNow that you've defined some of the types that were used in the previous section, let's move on and create the first view function nft_metadata. This will allow users to query for the contract's metadata as per the metadata standard.\n\n**************************************************\npub trait NonFungibleTokenMetadata {\n    //view call for returning the contract metadata\n    fn nft_metadata(\u0026self) -\u003e NFTContractMetadata;\n}\n\n#[near_bindgen]\nimpl NonFungibleTokenMetadata for Contract {\n    fn nft_metadata(\u0026self) -\u003e NFTContractMetadata {\n        self.metadata.get().unwrap()\n    }\n}\n**************************************************\n\n##mint.rs##\n\nLooking at these data structures, you could do the following:\n\n - Add the token ID into the set of tokens that the receiver owns. This will be done on the tokens_per_owner field.\n - Create a token object and map the token ID to that token object in the tokens_by_id field.\n - Map the token ID to it's metadata using the token_metadata_by_id.\n\n**************************************************\n#[near_bindgen]\nimpl Contract {\n    #[payable]\n    pub fn nft_mint(\n        \u0026mut self,\n        token_id: TokenId,\n        metadata: TokenMetadata,\n        receiver_id: AccountId,\n    ) {\n        //measure the initial storage being used on the contract\n        let initial_storage_usage = env::storage_usage();\n\n        //specify the token struct that contains the owner ID \n        let token = Token {\n            //set the owner ID equal to the receiver ID passed into the function\n            owner_id: receiver_id,\n        };\n\n        //insert the token ID and token struct and make sure that the token doesn't exist\n        assert!(\n            self.tokens_by_id.insert(\u0026token_id, \u0026token).is_none(),\n            \"Token already exists\"\n        );\n\n        //insert the token ID and metadata\n        self.token_metadata_by_id.insert(\u0026token_id, \u0026metadata);\n\n        //call the internal method for adding the token to the owner\n        self.internal_add_token_to_owner(\u0026token.owner_id, \u0026token_id);\n\n        //calculate the required storage which was the used - initial\n        let required_storage_in_bytes = env::storage_usage() - initial_storage_usage;\n\n        //refund any excess storage if the user attached too much. Panic if they didn't attach enough to cover the required.\n        refund_deposit(required_storage_in_bytes);\n    }\n}\n**************************************************\n\n##internal.rs##\nNow we must write internal methods for Mint_NFT\n\n**************************************************\nuse crate::*;\nuse near_sdk::{CryptoHash};\n\n//used to generate a unique prefix in our storage collections (this is to avoid data collisions)\npub(crate) fn hash_account_id(account_id: \u0026AccountId) -\u003e CryptoHash {\n    //get the default hash\n    let mut hash = CryptoHash::default();\n    //we hash the account ID and return it\n    hash.copy_from_slice(\u0026env::sha256(account_id.as_bytes()));\n    hash\n}\n\n//refund the initial deposit based on the amount of storage that was used up\npub(crate) fn refund_deposit(storage_used: u64) {\n    //get how much it would cost to store the information\n    let required_cost = env::storage_byte_cost() * Balance::from(storage_used);\n    //get the attached deposit\n    let attached_deposit = env::attached_deposit();\n\n    //make sure that the attached deposit is greater than or equal to the required cost\n    assert!(\n        required_cost \u003c= attached_deposit,\n        \"Must attach {} yoctoNEAR to cover storage\",\n        required_cost,\n    );\n\n    //get the refund amount from the attached deposit - required cost\n    let refund = attached_deposit - required_cost;\n\n    //if the refund is greater than 1 yocto NEAR, we refund the predecessor that amount\n    if refund \u003e 1 {\n        Promise::new(env::predecessor_account_id()).transfer(refund);\n    }\n}\n\nimpl Contract {\n    //add a token to the set of tokens an owner has\n    pub(crate) fn internal_add_token_to_owner(\n        \u0026mut self,\n        account_id: \u0026AccountId,\n        token_id: \u0026TokenId,\n    ) {\n        //get the set of tokens for the given account\n        let mut tokens_set = self.tokens_per_owner.get(account_id).unwrap_or_else(|| {\n            //if the account doesn't have any tokens, we create a new unordered set\n            UnorderedSet::new(\n                StorageKey::TokenPerOwnerInner {\n                    //we get a new unique prefix for the collection\n                    account_id_hash: hash_account_id(\u0026account_id),\n                }\n                .try_to_vec()\n                .unwrap(),\n            )\n        });\n\n        //we insert the token ID into the set\n        tokens_set.insert(token_id);\n\n        //we insert that set for the given account ID. \n        self.tokens_per_owner.insert(account_id, \u0026tokens_set);\n    }\n} \n**************************************************\n\nNow We Completed the Smart Contract\n\n4. Build, Deploy Smart Contract and Mint NFT\n\nFirst Step :\n\nBuild and deploy Smart Contract\n\n``yarn build``\n\n``near login``\n\nTo make this tutorial easier to copy/paste, we're going to set an environment variable for your account ID. In the command below, replace YOUR_ACCOUNT_NAME with the account name you just logged in with including the .testnet portion:\n\n``export NFT_CONTRACT_ID=\"YOUR_ACCOUNT_NAME\"``\n\n``echo $NFT_CONTRACT_ID``\n\nDeploy Smart Contract\n\n``near deploy --wasmFile out/main.wasm --accountId $NFT_CONTRACT_ID``\n\nSecond Step : \n\nInitialize the Contract\n\n``near call $NFT_CONTRACT_ID new_default_meta '{\"owner_id\": \"'$NFT_CONTRACT_ID'\"}' --accountId $NFT_CONTRACT_ID``\n\nView Metadata\n\n``near view $NFT_CONTRACT_ID nft_metadata``\n\nThird Step : \n\nMint NFT\n\n``\nnear call $NFT_CONTRACT_ID nft_mint '{\"token_id\": \"token-1\", \"metadata\": {\"title\": \"Seed Academy First Near NFT\", \"description\": \"This is Seed Academy First Near NFT\", \"media\": \"https://www.arweave.net/5_f4rixgIXZEEkOypQsZfj1H8mm5D29UiQT0TxEwtlY?ext=png\"}, \"receiver_id\": \"'$NFT_CONTRACT_ID'\"}' --accountId $NFT_CONTRACT_ID --amount 0.1\n``\n\nView NFT\n\n``\nnear view $NFT_CONTRACT_ID nft_token '{\"token_id\": \"token-1\"}'\n``\n\nYou can check the NFT on your Near Wallet too.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustyneuron01%2Fnearmint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frustyneuron01%2Fnearmint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustyneuron01%2Fnearmint/lists"}