shell-wallet-nft 0.17.0

Basic implementation cw721 NFTs
Documentation
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{to_binary, Binary, Empty, Deps, DepsMut, Env, MessageInfo, Response, StdResult, WasmMsg};
use cw2::set_contract_version;


use crate::error::ContractError;

use cw721::{Cw721Query,NftInfoResponse};

use cw721_base::{
    InstantiateMsg as cw721InstantiateMsg,
    ExecuteMsg as cw721ExecuteMsg,
    Cw721Contract,
    Extension,
};

use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg, GetNFTIndexResponse};
use crate::state::{increment_token_index, TOKEN_INDEX};

// version info for migration info
const CONTRACT_NAME: &str = "crates.io:shell-wallet-nft";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

const NFT_NAME: &str = "ShellPower";
const NFT_SYMBOL: &str = "SPX";

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    _msg: InstantiateMsg,
) -> Result<Response, ContractError> {
    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
    let contract = Cw721Contract::<Extension, Empty, Empty, Empty>::default();
    let contract_address = String::from(env.contract.address.clone());
    let cw721msg = cw721InstantiateMsg{
        name: NFT_NAME.to_string(),
        symbol: NFT_SYMBOL.to_string(),
        minter: contract_address.clone(),
    };

    let _res = contract.instantiate(deps, env, info, cw721msg);
    
    Ok(Response::new()
        .add_attribute("method", "instantiate")
        .add_attribute("contract-address", contract_address)
    )
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> Result<Response, ContractError> {
    match msg {
        ExecuteMsg::Mint {} => execute::mint_nft(deps, _env, info),
    }
}

pub mod execute {
    use super::*;

    pub fn mint_nft(deps:DepsMut, _env: Env, info: MessageInfo) -> Result<Response, ContractError>{
        let contract = Cw721Contract::<Extension, Empty, Empty, Empty>::default();
        let token_uri = "https://shell.io/nft/minter/ShellPowerMeta.json";
        let token_id = increment_token_index(deps.storage)?.to_string();
        let mint_msg = cw721ExecuteMsg::<Empty, Empty>::Mint {
            token_id: token_id.clone(),
            owner: info.sender.to_string(),
            token_uri: Some(token_uri.to_string()),
            extension: Empty::default(),
        };

        WasmMsg::Execute {
            contract_addr: _env.contract.address.into(),
            msg: to_binary(&mint_msg)?,
            funds: vec![],
        };
    
        let count = contract.num_tokens(deps.as_ref()).unwrap();
        assert_eq!(1, count.count);


        // unknown nft returns error
        let _ = contract
            .nft_info(deps.as_ref(), "unknown".to_string())
            .unwrap_err();

        // this nft info is correct
        let nft_info = contract.nft_info(deps.as_ref(), token_id.clone()).unwrap();
        assert_eq!(
            nft_info,
            NftInfoResponse::<Extension> {
                token_uri: Some(token_uri.to_string()),
                extension: None,
            }
        );

        // list the token_ids
        let _tokens = contract.all_tokens(deps.as_ref(), None, None).unwrap();

        Ok(Response::new()
            .add_attribute("action", "mint NFT")
            .add_attribute("token_id", token_id)
            .add_attribute("contract_version", CONTRACT_VERSION)
            .add_attribute("sender", info.sender.to_string())
        )
    }
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
        QueryMsg::GetNFTIndex {} => to_binary(&query::count(_deps)?),
    }
}

pub mod query {
    use super::*;

    pub fn count(deps: Deps) -> StdResult<GetNFTIndexResponse> {
        let state = TOKEN_INDEX.load(deps.storage)?;
        Ok(GetNFTIndexResponse { index: state })
    }
}