# Quick start developing with TIP-4

## Source Code

You can inspect the source code of TIP-4 token implementation by [link](https://github.com/itgoldio/everscale-tip).

## How to deploy your own NFT collection

{% hint style="info" %}
You need to have an installed Smart Contract Development Environment. If you haven't already, follow [this tutorial](/knowledge-base/build/development-guides/setting-up-a-venom-smart-contract-development-environment.md).
{% endhint %}

### Initialize your NFT project

```
npx locklift init --path my-first-nft
> [INFO]  New Locklift project initialized in .
> [INFO]  Installing required dependencies...
> [INFO]  
> added 181 packages, and audited 182 packages in 13s

> 23 packages are looking for funding
>   run `npm fund` for details

> found 0 vulnerabilities

> [INFO]  LockLift initialized in my-first-nft happy hacking!
```

### Install dependencies

TIP-4 is accessible from npm. Let's install it

```shell
npm i --save-dev @itgold/everscale-tip
```

### Implement base contracts

Next, you should implement two interfaces in two contracts. Firstly, let's deal with Nft contract. The only thing we should do for basics is implement `TIP4_1Nft`&#x20;

{% code title="Nft.sol" lineNumbers="true" %}

```solidity
pragma ever-solidity >= 0.61.2;

pragma AbiHeader expire;
pragma AbiHeader time;
pragma AbiHeader pubkey;

import '@itgold/everscale-tip/contracts/TIP4_1/TIP4_1Nft.sol';

contract Nft is TIP4_1Nft {

    constructor(
        address owner,
        address sendGasTo,
        uint128 remainOnNft
    ) TIP4_1Nft(
        owner,
        sendGasTo,
        remainOnNft
    ) public {}

}
```

{% endcode %}

Now we should go for Collection contract. We should implement `TIP4_1Collection` and write some method for NFT deploying.

{% code title="Collection.sol" lineNumbers="true" %}

```solidity
pragma ever-solidity >= 0.61.2;

pragma AbiHeader expire;
pragma AbiHeader time;
pragma AbiHeader pubkey;

import '@itgold/everscale-tip/contracts/TIP4_1/TIP4_1Collection.sol';
import './Nft.sol';

contract Collection is TIP4_1Collection {

    constructor(
        TvmCell codeNft
    ) TIP4_1Collection (
        codeNft
    ) public {
        tvm.accept();
    }

    function mintNft() external virtual {
        require(msg.value > 0.4 ever, 101);
        tvm.rawReserve(0, 4);

        uint256 id = uint256(_totalSupply);
        _totalSupply++;

        TvmCell codeNft = _buildNftCode(address(this));
        TvmCell stateNft = tvm.buildStateInit({
            contr: Nft,
            varInit: {_id: id},
            code: codeNft
        });
        new Nft{
            stateInit: stateNft,
            value: 0,
            flag: 128
        }(
            msg.sender,
            msg.sender,
            0.3 ever
        );     
    }
}
```

{% endcode %}

### Deploy action

Let's move to deploy action. We need two scripts for this quick start: one for `Collection` deploying, and second for calling `mintNft` function, that we have implemented.

{% code title="1-deploy-collection.ts" lineNumbers="true" %}

```typescript
async function main() {
  const signer = (await locklift.keystore.getSigner("0"))!;
  const nftArtifacts = await locklift.factory.getContractArtifacts("NFT");
  const { contract: sample, tx } = await locklift.factory.deployContract({
    contract: "Collection",
    publicKey: signer.publicKey,
    initParams: {},
    constructorParams: {
      codeNft: nftArtifacts.code,
    },
    value: locklift.utils.toNano(5),
  });

  console.log(`Collection deployed at: ${sample.address.toString()}`);
}

main()
  .then(() => process.exit(0))
  .catch(e => {
    console.log(e);
    process.exit(1);
  });

```

{% endcode %}

{% code title="2-call-mintNft.ts" lineNumbers="true" %}

```typescript
import { toNano, WalletTypes } from "locklift";

// you can get this parameter as (await locklift.keystore.getSigner("0"))! if you have a seed phrase sets up in key section of locklift config
// or you can pass this parameter by cli or get them by some file reading for example
// if phrase or secret was not set up in key section, calling (await locklift.keystore.getSigner("0"))! will give you a different results from launch to lauch
// we just hardcode it here
const COLLECTION_DEPLOY_PUBLIC_KEY = "e85f61aaef0ea43afc14e08e6bd46c3b996974c495a881baccc58760f6349300"

async function main() {
    const signer = (await locklift.keystore.getSigner("0"))!;
    const collectionArtifacts = await locklift.factory.getContractArtifacts("Collection");
    const nftArtifacts = await locklift.factory.getContractArtifacts("NFT");

    // calculation of deployed Collection contract address
    const collectionAddress = await locklift.provider.getExpectedAddress(
        collectionArtifacts.abi,
        {
            tvc: collectionArtifacts.tvc,
            publicKey: COLLECTION_DEPLOY_PUBLIC_KEY,
            initParams: {} // we don't have any initParams for collection
        }
    );
    // initialize contract object by locklift
    const collectionInsance = await locklift.factory.getDeployedContract(
        "Collection",
        collectionAddress
    );

    // creating new account for Collection calling (or you can get already deployed by locklift.factory.accounts.addExistingAccount)
    const { account: someAccount } = await locklift.factory.accounts.addNewAccount({
        type: WalletTypes.WalletV3,
        value: toNano(10),
        publicKey: signer.publicKey
    });
    // call mintNft function
    // firstly get current nft id (totalSupply) for future NFT address calculating
    const {count: id} = await collectionInsance.methods.totalSupply({ answerId: 0 }).call();
    await collectionInsance.methods.mintNft({}).send({ from: someAccount.address, amount: toNano(1)});
    const {nft: nftAddress} = await collectionInsance.methods.nftAddress({ answerId: 0, id: id }).call();
  
    console.log(`NFT: ${nftAddress.toString()}`);
}
  
main()
    .then(() => process.exit(0))
    .catch(e => {
        console.log(e);
        process.exit(1);
    });
  
```

{% endcode %}

Finally, we can deploy a new token to `local` network. For this, make sure local node is running, if not follow the next command

<pre class="language-shell"><code class="lang-shell"><strong>docker run -d --name local-node -e USER_AGREEMENT=yes -p80:80 tonlabs/local-node
</strong></code></pre>

and run our scripts

<pre class="language-shell"><code class="lang-shell">npx locklift run -s ./scripts/1-deploy-collection.ts -n local
> [INFO]  factorySource generated
<strong>> [INFO]  Built
</strong>> Collection deployed at: 0:882c1f7af09efaf506ab313daecb6ce127acfab7d082e28e6dbcff839aa58bba
npx locklift run -s ./scripts/2-call-mintNft.ts -n local
> [INFO]  factorySource generated
> [INFO]  Built
> NFT: 0:64a4ea8fa80bf3d2ba78c0a602e39a045786a70b69e879f90e9abe2a2f7f33fe
</code></pre>

Now you know how to deploy your own NFT collection and mint NFT with TIP-4 standard!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://venom-docs.gitbook.io/knowledge-base/build/development-guides/how-to-create-your-own-non-fungible-tip-4-token/quick-start-developing-with-tip-4.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
