# NFT

`NFT` means non-fungible token, that is, each token is unique.

And `KIC721` is a standard for representing ownership of [non-fungible tokens](https://docs.openzeppelin.com/contracts/3.x/tokens#different-kinds-of-tokens) in Ethereum.

`KIC` is fully compatible with Ethereum [ERC721](https://eips.ethereum.org/EIPS/eip-721) Standard.

```
// ----------------------------------------------------------------------------
// CRC Token Standard #721 Interface
// ----------------------------------------------------------------------------
contract KRC721Interface {
    function balanceOf(address _owner) external view returns (uint256);
    function ownerOf(uint256 _tokenId) external view returns (address);
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function approve(address _approved, uint256 _tokenId) external payable;
    function setApprovalForAll(address _operator, bool _approved) external;
    function getApproved(uint256 _tokenId) external view returns (address);
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);

    // ERC165
    function supportsInterface(bytes4 interfaceID) external view returns (bool);

    // Optional
    function name() external view returns (string _name);
    function symbol() external view returns (string _symbol);
    function tokenURI(uint256 _tokenId) external view returns (string);

    function totalSupply() external view returns (uint256);
    function tokenByIndex(uint256 _index) external view returns (uint256);
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);

    // Event
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
}
```

* For standard, refer to [ERC721](https://eips.ethereum.org/EIPS/eip-721)
* For implementation, refer to [OpenZeppelin-ERC721](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721)

## KIC721 Operation

### KRC721 ABI <a href="#krc721-abi" id="krc721-abi"></a>

```
ABI = '[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]'
```

### Connect KIC public nodes <a href="#connect-kic-public-nodes" id="connect-kic-public-nodes"></a>

#### **Javascript**

* Mainnet

```
const Web3 = require('web3');
const w3 = new Web3("https://rpc.koisan-chain.com");
```

* Testnet

```
const Web3 = require('web3');
const w3 = new Web3("https://testnet-rpc.koisan-chain.com");
```

#### **Python3**

* Mainnet

```python
from web3 import Web3
provider = Web3.HTTPProvider("https://rpc.koisan-chain.com")
w3 = Web3(provider)
```

* Testnet

```python
from web3 import Web3
provider = Web3.HTTPProvider("https://testnet-rpc.koisan-chain.com")
w3 = Web3(provider)
```

### KIC721 Inquiry <a href="#krc721-inquiry" id="krc721-inquiry"></a>

#### **Javascript**

```javascript
const krc721_abi = "<krc721 contract abi>";
const contranctAddress = "<krc721 token address>";
const crcContract = new web3.eth.Contract(krc721_abi, contranctAddress);

// get name of krc721 token
const name = crcContract.methods.name().call();

// get balance of address
const userAddress = '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'; // a user address
const balance = crcContract.methods.balanceOf(userAddress).call();

// ...
```

#### **Python3**

```python
krc721_address = "<krc721 token address>" 
krc721_address = Web3.toChecksumAddress(krc721_address)
krc721_abi = "<krc721 contract abi>"

# construct a krc721 contract object
contract = w3.eth.contract(krc721_address, abi=krc721_abi)

# get name of krc721 token
name = contract.functions.name().call()

# get balance of address
address = '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'     # a user address
balance = contract.functions.balanceOf(address).call()

# ...
```

### KIC721 Transaction <a href="#krc721-transaction" id="krc721-transaction"></a>

#### **Javascript**

```javascript
// krc721 safeTransferFrom

const fromAddress = '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe';
const toAddress = '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe';
const tokenId = 1;

// construct the krc721 safeTransferFrom transaction
const data = crcContract.methods.safeTransferFrom(fromAddress, toAddress, tokenId).encodeABI();

web3.eth.sendTransaction({
  from: sender,                        // transaction sender address
  to: contranctAddress,     // krc721 contract address
  data
}, function(error, hash){
    // handler here
});

// ...
```

#### **Python3**

```python
# krc721 safeTransferFrom

krc721_address = Web3.toChecksumAddress(krc721_address)
contract = w3.eth.contract(krc721_address, abi=krc721_abi)

# unlock a account
account_keyfile = "./keystore/XXXXXXXXXXXXXX"
password = "XXXXXXX"
w3 = get_web3_instance()
keyfile_json = eth_keyfile.load_keyfile(account_keyfile)
private_key_bytes = eth_keyfile.decode_keyfile_json(keyfile_json, password.encode('utf-8'))
account = w3.eth.account.privateKeyToAccount(private_key_bytes)

# get nonce of account
nonce = w3.eth.getTransactionCount(account.address)

# estimate gas
tx_obj = {'from': account.address, 'nonce': nonce}
gas = contract.functions.safeTransferFrom(fromAddress, toAddress, tokenId).estimateGas(tx_obj)

# get gas price
gas_price = w3.eth.gasPrice

tx_obj['gas'] = gas
tx_obj['gasPrice'] = gas_price

# construct the krc721 safeTransferFrom transaction and sign
transaction = contract.functions.safeTransferFrom(fromAddress, toAddress, tokenId).buildTransaction(tx_obj)
signed = account.signTransaction(transaction)

# broadcast the signed transaction
tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction)
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)

# ...
```


---

# 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://worldkoisan.gitbook.io/koisan-international-coin/koisan-chain/dapp-development/nft.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.
