Fetch Data Example
This section will guide you through fetching contract state data from the blockchain using a Node RPC provider.
Contracts:
KIPIdentification
Contract: 0x3cDfD20F5AA27335bE4A68d0e1B1085A65418b09Retrieve the
owner
of a giventokenId
Retrieve the
tokenURI
of a giventokenId
Mock
KIPToken
Contract: 0x4b565A132347064Ca7F1eDC9489a00b3E68431ddRetrieve the current balance of an
account
Retrieve the
allowance
amount that anaccount
has granted to aspender
Prerequisites:
RPC Node Provider: Alchemy, Infura, or others.
NodeJS: version
v20.14.0
orv20.15.0
.Package Manager:
yarn
ornpm
.
Fetch Data Example
Folder Structure:
fetch-data-example
├── package.json
├── src
│ ├── abis
│ │ ├── KIPIdentification.json
│ │ └── MockKIPToken.json
│ ├── fetchKIPIdentification.ts
│ ├── fetchKIPToken.ts
│ └── main.ts
└── tsconfig.json
Let's get started:
Create a project folder:
mkdir fetch-data-example && cd fetch-data-example
Create
package.json
and install dependencies:
Create
package.json
touch package.json && open package.json
Add the following content to
package.json
:
{
"name": "fetch-data-example",
"version": "1.0.0"
}
Install dependencies:
yarn add @types/node dotenv ethers typescript
# or
npm install --save-dev @types/node dotenv ethers typescript
Create
tsconfig.json
:
Create the file:
touch tsconfig.json && open tsconfig.json
Add the following content to
tsconfig.json
:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"resolveJsonModule": true
},
"include": ["src"]
}
Create
.env
file:
Create the file:
touch .env && open .env
Add the following content to
.env
:
// Provide your Node RPC URL that created in another section
RPC_URL=<YOUR_RPC_URL>
Create
src
andabis
folders:
mkdir -p src/abis && cd src/abis
Create ABI files for the smart contracts:
KIPIdentification
Contract ABI:
// make sure your current directory is "./src/abis"
touch KIPIdentification.json && open KIPIdentification.json
Add the ABI content to
KIPIdentification.json
:
[{"inputs":[{"internalType":"contract IKIPManagement","name":"management","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressZero","type":"error"},{"inputs":[],"name":"AdminRequire","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[],"name":"MinterRequire","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"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":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"idType","type":"uint256"}],"name":"KIPIdentity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","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":[],"name":"KIPManagement","outputs":[{"internalType":"contract IKIPManagement","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"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":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"idTypes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"idType","type":"uint256"},{"internalType":"string","name":"tokenURI","type":"string"}],"name":"issueId","outputs":[],"stateMutability":"nonpayable","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":"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":"address","name":"management","type":"address"}],"name":"setManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenURI","type":"string"}],"name":"setTokenURI","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"}]
Mock
KIPToken
Contract ABI:
// make sure your current directory is "./src/abis"
touch MockKIPToken.json && open MockKIPToken.json
Add the ABI content to
MockKIPToken.json
:
[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Create scripts to interact with the contracts:
Fetch data from
KIPIdentification
contract:
cd ..
# Ensure you are in the "src" directory before running a following command
touch fetchKIPIdentification.ts && open fetchKIPIdentification.ts
Add the code to interact with the
KIPIdentification
contract intofetchKIPIdentification.ts
:
import { AddressLike, ethers } from "ethers";
import ABI from "./abis/KIPIdentification.json";
import * as dotenv from "dotenv";
dotenv.config();
// Change CONTRACT_ADDRESS to match your contract if needed
const CONTRACT_ADDRESS = "0x3cDfD20F5AA27335bE4A68d0e1B1085A65418b09";
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL as string);
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider);
export const getOwner = async (
tokenId: bigint | string
): Promise<AddressLike> => {
return await contract.ownerOf(tokenId);
};
export const getTokenURI = async (
tokenId: bigint | string
): Promise<string> => {
return await contract.tokenURI(tokenId);
};
Fetch data from the mock
KIPToken
contract:
touch fetchKIPToken.ts && open fetchKIPToken.ts
Add the code to interact with the mock
KIPToken
contract intofetchKIPToken.ts
:
import { AddressLike, ethers } from "ethers";
import ABI from "./abis/MockKIPToken.json";
import * as dotenv from "dotenv";
dotenv.config();
// Change CONTRACT_ADDRESS to match your contract if needed
const CONTRACT_ADDRESS = "0x4b565A132347064Ca7F1eDC9489a00b3E68431dd";
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL as string);
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider);
export const getBalance = async (account: AddressLike): Promise<BigInt> => {
return await contract.balanceOf(account);
};
export const getAllowance = async (
owner: AddressLike,
spender: AddressLike
) => {
return await contract.allowance(owner, spender);
};
Create
main.ts
to test the setup:
Create the file:
touch main.ts && open main.ts
Add the code into
main.ts
:
import { getOwner, getTokenURI } from "./fetchKIPIdentification";
import { getAllowance, getBalance } from "./fetchKIPToken";
async function main() {
const tokenId = BigInt(1);
const owner = await getOwner(tokenId);
console.log(`Owner of tokenId = ${tokenId}: ${owner}`);
const tokenURI = await getTokenURI(tokenId);
console.log(`TokenURI of tokenId = ${tokenId}: ${tokenURI}`);
// Change `account` and `spender` addresses for your case
const account = "0x31003C2D5685c7D28D7174c3255307Eb9a0f3015";
const balance = await getBalance(account);
console.log(`Balance of ${account}: ${balance}`);
const spender = "0x87a7A0223D6F96B3DECaAf3666d5c550b36fEfEe";
const allowance = await getAllowance(account, spender);
console.log(
`Spender ${spender} is allowed to spend: ${allowance} on the ${account} behalf`
);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Run the test:
cd ..
# Ensure your current directory is "fetch-data-example"
npx ts-node src/main.ts
After running, you should see output similar to the following:
(base) ➜ fetch-data-example npx ts-node src/main.ts
Owner of tokenId = 1: 0x31003C2D5685c7D28D7174c3255307Eb9a0f3015
TokenURI of tokenId = 1: ipfs://QmZcH4YvBVVRJtdn4RdbaqgspFU8gH6P9vomDpBVpAL3u4/4375
Balance of 0x31003C2D5685c7D28D7174c3255307Eb9a0f3015: 100880000000000000000420
Spender 0x87a7A0223D6F96B3DECaAf3666d5c550b36fEfEe is allowed to spend: 0 on the 0x31003C2D5685c7D28D7174c3255307Eb9a0f3015 behalf
(base) ➜ fetch-data-example
Last updated