NFT

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

And KIC721 is a standard for representing ownership of non-fungible tokens in Ethereum.

KIC is fully compatible with Ethereum ERC721 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);
}

KIC721 Operation

KRC721 ABI

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

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

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

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

KIC721 Inquiry

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

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

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

# 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)

# ...

Last updated