Giter VIP home page Giter VIP logo

nft-tutorial's Introduction

NEAR NFT-Tutorial

Welcome to NEAR's NFT tutorial, where we will help you parse the details around NEAR's NEP-171 standard (Non-Fungible Token Standard), and show you how to build your own NFT smart contract from the ground up, improving your understanding about the NFT standard along the way.

Prerequisites

Tutorial Stages

Each branch you will find in this repo corresponds to various stages of this tutorial with a partially completed contract at each stage. You are welcome to start from any stage you want to learn the most about.

Branch Docs Tutorial Description
1.skeleton Contract Architecture You'll learn the basic architecture of the NFT smart contract, and you'll compile this skeleton code with the Rust toolchain.
2.minting Minting Here you'll flesh out the skeleton so the smart contract can mint a non-fungible token
3.enumeration Enumeration Here you'll find different enumeration methods that can be used to return the smart contract's states.
4.core Core In this tutorial you'll extend the NFT contract using the core standard, which will allow you to transfer non-fungible tokens.
5.approval Approval Here you'll expand the contract allowing other accounts to transfer NFTs on your behalf.
6.royalty Royalty Here you'll add the ability for non-fungible tokens to have royalties. This will allow people to get a percentage of the purchase price when an NFT is purchased.
7.events Events This allows indexers to know what functions are being called and make it easier and more reliable to keep track of information that can be used to populate the collectibles tab in the wallet for example. (tutorial docs have yet to be implemented )
8.marketplace Marketplace Get a comprehensive understanding of how an NFT marketplace contract can be built on NEAR through this tutorial. This contract facilitates the buying and selling of non-fungible tokens with $NEAR.

The tutorial series also contains a very helpful section on Upgrading Smart Contracts. Definitely go and check it out as this is a common pain point.

Quick-Start

If you want to see the full completed contract go ahead and clone and build this repo using

git clone https://github.com/near-examples/nft-tutorial.git 
cd nft-tutorial
git switch 6.royalty
yarn build

Now that you've cloned and built the contract we can try a few things.

Mint An NFT

Once you've created your near wallet go ahead and login to your wallet with your cli and follow the on-screen prompts

near login

Once your logged in you have to deploy the contract. Make a subaccount with the name of your choosing

near create-account nft-example.your-account.testnet --masterAccount your-account.testnet --initialBalance 10

After you've created your sub account deploy the contract to that sub account, set this variable to your sub account name

NFT_CONTRACT_ID=nft-example.your-account.testnet

MAIN_ACCOUNT=your-account.testnet

Verify your new variable has the correct value

echo $NFT_CONTRACT_ID

echo $MAIN_ACCOUNT

Deploy Your Contract

near deploy --accountId $NFT_CONTRACT_ID --wasmFile out/main.wasm

Initialize Your Contract

near call $NFT_CONTRACT_ID new_default_meta '{"owner_id": "'$NFT_CONTRACT_ID'"}' --accountId $NFT_CONTRACT_ID

View Contracts Meta Data

near view $NFT_CONTRACT_ID nft_metadata

Minting Token

near call $NFT_CONTRACT_ID nft_mint '{"token_id": "token-1", "metadata": {"title": "My Non Fungible Team Token", "description": "The Team Most Certainly Goes :)", "media": "https://bafybeiftczwrtyr3k7a2k4vutd3amkwsmaqyhrdzlhvpt33dyjivufqusq.ipfs.dweb.link/goteam-gif.gif"}, "receiver_id": "'$MAIN_ACCOUNT'"}' --accountId $MAIN_ACCOUNT --amount 0.1

After you've minted the token go to wallet.testnet.near.org to your-account.testnet and look in the collections tab and check out your new sample NFT!

View NFT Information

After you've minted your NFT you can make a view call to get a response containing the token_id owner_id and the metadata

near view $NFT_CONTRACT_ID nft_token '{"token_id": "token-1"}'

Transfering NFTs

To transfer an NFT go ahead and make another testnet wallet account.

Then run the following

MAIN_ACCOUNT_2=your-second-wallet-account.testnet

Verify the correct variable names with this

echo $NFT_CONTRACT_ID

echo $MAIN_ACCOUNT

echo $MAIN_ACCOUNT_2

To initiate the transfer..

near call $NFT_CONTRACT_ID nft_transfer '{"receiver_id": "$MAIN_ACCOUNT_2", "token_id": "token-1", "memo": "Go Team :)"}' --accountId $MAIN_ACCOUNT --depositYocto 1

In this call you are depositing 1 yoctoNEAR for security and so that the user will be redirected to the NEAR wallet.

Errata

Large Changes:

  • 2022-06-21: updated the rust SDK to version 4.0.0. PR found here

  • 2022-02-12: updated the enumeration methods nft_tokens and nft_tokens_for_owner to no longer use any to_vector operations to save GAS. In addition, the default limit was changed from 0 to 50. PR found here.

Small Changes:

  • 2022-02-22: changed token_id parameter type in nft_payout from String to TokenId for consistency as per pythonicode's suggestion

nft-tutorial's People

Contributors

benkurrek avatar bucanero avatar devendra116 avatar doriancrutcher avatar emarai avatar gagdiez avatar garikbesson avatar idea404 avatar mattlockyer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

nft-tutorial's Issues

yarn build problem

});
const promise = promiseFn.apply(null, args);
try {
await promise;
} catch (e) {

PLEASE help me am new to rust

Yarn build fails

I'm trying to follow the minting tutorial from https://docs.near.org/tutorials/nfts/minting. I followed the guide exactly the same. However, after making all the mentioned changes when I run yarn build I get following errors.

image

General question about contracts!

Hi NEAR developers,

I am traversing your guides and I am quite impressed with the work you done.

I have a question regrading contracts. I started using my actual near account xxxx.near and not xxxx.testnet anymore.
Will I be able to make near calls with deployed contract from

git clone https://github.com/near-examples/nft-tutorial.git 
cd nft-tutorial
git switch 6.royalty
yarn build

then I call
near deploy --accountId $NFT_CONTRACT_ID --wasmFile out/main.wasm
to deploy contract

then I call

near call $NFT_CONTRACT_ID new_default_meta '{"owner_id": "'$NFT_CONTRACT_ID'"}' --accountId $NFT_CONTRACT_ID

to init contract.

Will I be able to then call a function

near view $MARKETPLACE_CONTRACT_ID get_supply_sales

with contract that I previously deployed?

I do not want to spend to much NEAR on deploying and initializing contracts that does not do its job. I need to pay I think 3 NEAR (2937818518636002900000000 yocto) to deploy.

Thank you for your answers and help

Tutorial stage links non-functional

On the ReadMe for this repository, the Tutorial Stages table that explains the step-by-step way to learn how to make a near contract all return "page not found".

Testing for Reselling with Royalties Fails

Currently there is no testing flow for reselling an NFT with royalties. When implementing this with near-workspaces-ava, the asserts fail when running the following simulation test:

workspace.test(
  "cross contract: reselling and royalties",
  async (test, { nft_contract, market_contract, alice, bob, charlie }) => {
    const royalties_string = `{"${alice.accountId}":2000}`;
    const royalties = JSON.parse(royalties_string);
    test.log("royalties: ", royalties);
    await mintNFT(alice, nft_contract, royalties);
    await payForStorage(alice, market_contract);
    const ask_price = "300000000000000000000000";
    await placeNFTForSale(market_contract, alice, nft_contract, ask_price);

    // offer for higher price
    const alice_balance_before_offer = (await alice.balance()).total.toBigInt();
    const bid_price = ask_price + "0";
    await purchaseListedNFT(nft_contract, bob, market_contract, bid_price);
    const alice_balance_after_offer = (await alice.balance()).total.toBigInt();
    const alice_balance_difference = (
      alice_balance_after_offer - alice_balance_before_offer
    ).toString();

    // assert alice gets paid
    test.is(
      alice_balance_difference.substring(0, 3),
      bid_price.substring(0, 3),
      "Expected alice balance to roughly increase by sale price"
    );

    // bob relists NFT for higher price
    test.log("bob paying for storage");
    await payForStorage(bob, market_contract);
    const resell_ask_price = bid_price + "0";
    test.log("bob placing NFT for sale");
    await placeNFTForSale(market_contract, bob, nft_contract, resell_ask_price);
  
    // bob updates price to lower ask
    test.log("bob updating NFT price for lower");
    const lowered_resell_ask_price = "600000000000000000000000";
    const update_price_payload = {
      nft_contract_id: nft_contract,
      token_id: "TEST123",
      price: lowered_resell_ask_price,
    };
    await bob.call(
      market_contract,
      "update_price",
      update_price_payload,
      defaultCallOptions(DEFAULT_GAS, "1")
    );

    // charlie buys NFT from bob
    test.log("charlie purchasing bobs NFT");
    const alice_balance_before_offer_2 = (
      await alice.balance()
    ).total.toBigInt();
    const bob_balance_before_offer = (await bob.balance()).total.toBigInt();
    test.log("bob_balance_before_offer", bob_balance_before_offer);
    await purchaseListedNFT(
      nft_contract,
      charlie,
      market_contract,
      resell_ask_price
    );
    const alice_balance_after_offer_2 = (
      await alice.balance()
    ).total.toBigInt();
    const alice_balance_difference_2 = (
      alice_balance_after_offer_2 - alice_balance_before_offer_2
    ).toString();
    const bob_balance_after_offer = (await bob.balance()).total.toBigInt();
    test.log("bob_balance_after_offer", bob_balance_after_offer);
    const bob_balance_difference = (
      bob_balance_after_offer - bob_balance_before_offer
    ).toString();

    // assert alice gets paid royalties
    // TODO: this fails on sandbox and should pass 
    test.is(
      alice_balance_difference_2.substring(0, 2),
      "120", // 20% of lowered_resell_ask_price
      "Expected bob balance to roughly increase by 80% of sale price"
    );
    // assert bob gets paid
    test.is(
      bob_balance_difference.substring(0, 2),
      "480", // 80% of lowered_resell_ask_price
      "Expected bob balance to roughly increase by 80% of sale price"
    );
  }
);

List all NFT for particular account

Hi,

I am following https://docs.near.org/docs/tutorials/contracts/nfts/marketplace tutorial and I would like to call function near view $MARKETPLACE_CONTRACT_ID get_supply_by_owner_id '{"account_id": "benji.testnet"}' to list all supply that account_id: "benji.testnet" owns. But I am getting the following error Unknown argument: benji.testnet}'

Is this the right function call with its parameters, and should I get in return some sort of list with information?

What am I doing wrong?

With kind regards
Jernej

Some mandatory parameters on `nft_transfer` and `nft_transfer_payout` are not part of NFT standard

Hi, some new projects are using this example and we have found some parameters are mandatory (which shouldn't from the standard).

The first one is nft_transfer_payout, which requires a mandatory memo, which is not part of the standard [1]. This is also reflected in the tutorial [2].

https://github.com/near-examples/nft-tutorial/blob/main/nft-contract/src/royalty.rs#L69

 fn nft_transfer_payout(
        &mut self,
        receiver_id: AccountId,
        token_id: TokenId,
        approval_id: u64,
        memo: String,
        balance: U128,
        max_len_payout: u32,
 )

The second one is nft_transfer with mandatory approval_id, which should be optional from the standard [3].

https://github.com/near-examples/nft-tutorial/blob/main/nft-contract/src/nft_core.rs#L100

    fn nft_transfer(
       &mut self,
       receiver_id: AccountId,
       token_id: TokenId,
       //we introduce an approval ID so that people with that approval ID can transfer the token
       approval_id: u64,
       memo: Option<String>,
   ) {

[1] https://nomicon.io/Standards/NonFungibleToken/Payout
[2] https://docs.near.org/docs/tutorials/contracts/nfts/royalty
[3] https://nomicon.io/Standards/NonFungibleToken/Core

Edit: made a PR #21

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.