Read Contract
Use readContract() to call read-only (view / pure) functions on any deployed smart contract. The method does not send a transaction or cost gas -- it queries on-chain state and returns the result.
Method Signature
client.readContract(params: ContractReadParams): Promise<ApiResponse<unknown>>
ContractReadParams
import type { ContractReadParams } from '@one_deploy/sdk';
interface ContractReadParams {
contractAddress: string; // The deployed contract address
chainId: number; // Chain to read from
functionName: string; // Solidity function name
args?: unknown[]; // Positional arguments to the function
abi?: Record<string, unknown>[]; // ABI array (optional if contract is indexed)
}
When the contract has already been indexed by the Engine (e.g. you deployed it through the SDK or it is a well-known token), the abi field is optional. For unindexed contracts, provide at minimum the ABI fragment for the function you are calling.
ApiResponse Wrapper
Every Engine method returns a standardised ApiResponse<T> envelope:
interface ApiResponse<T> {
data: T;
success: boolean;
error?: {
code: string;
message: string;
};
meta?: Record<string, unknown>;
}
For readContract, T is inferred from the return type of the Solidity function. Because the Engine cannot know the type at compile time, the SDK types it as unknown -- you should cast or narrow the result in your application code.
Examples
ERC-20: balanceOf
import { useOneEngine } from '@one_deploy/sdk';
function TokenBalance({ token, wallet }: { token: string; wallet: string }) {
const { client } = useOneEngine();
async function fetchBalance() {
const res = await client.readContract({
contractAddress: token,
chainId: 137, // Polygon
functionName: 'balanceOf',
args: [wallet],
});
// balanceOf returns a uint256 -- the Engine serialises it as a string
const rawBalance = res.data as string;
console.log('Raw balance:', rawBalance);
}
return <button onClick={fetchBalance}>Check Balance</button>;
}
ERC-20: name, symbol, decimals
Read multiple properties in parallel using Promise.all:
const [nameRes, symbolRes, decimalsRes] = await Promise.all([
client.readContract({
contractAddress: '0xA0b8...3E7a',
chainId: 1,
functionName: 'name',
}),
client.readContract({
contractAddress: '0xA0b8...3E7a',
chainId: 1,
functionName: 'symbol',
}),
client.readContract({
contractAddress: '0xA0b8...3E7a',
chainId: 1,
functionName: 'decimals',
}),
]);
const name = nameRes.data as string; // "USD Coin"
const symbol = symbolRes.data as string; // "USDC"
const decimals = decimalsRes.data as number; // 6
ERC-721: ownerOf
const res = await client.readContract({
contractAddress: '0xBC4C...a1F9',
chainId: 1,
functionName: 'ownerOf',
args: [42], // tokenId
});
const owner = res.data as string;
console.log('Token #42 owner:', owner);
ERC-721: tokenURI
const res = await client.readContract({
contractAddress: '0xBC4C...a1F9',
chainId: 1,
functionName: 'tokenURI',
args: [42],
});
const uri = res.data as string;
// "ipfs://Qm.../42.json"
Custom Contract with ABI Fragment
When calling a function on a contract the Engine has not indexed, supply the ABI fragment directly:
const customAbi = [
{
inputs: [{ name: 'account', type: 'address' }],
name: 'getStakeInfo',
outputs: [
{ name: 'stakedAmount', type: 'uint256' },
{ name: 'rewardDebt', type: 'uint256' },
],
stateMutability: 'view',
type: 'function',
},
];
const res = await client.readContract({
contractAddress: '0x9988...ccDD',
chainId: 42161, // Arbitrum
functionName: 'getStakeInfo',
args: ['0xYourWallet...'],
abi: customAbi,
});
// Tuple returns are serialised as an array
const [stakedAmount, rewardDebt] = res.data as [string, string];
console.log('Staked:', stakedAmount, 'Reward debt:', rewardDebt);
Error Handling
const res = await client.readContract({
contractAddress: '0xDEAD...0000',
chainId: 1,
functionName: 'balanceOf',
args: ['0xUser...'],
});
if (!res.success) {
console.error(`Read failed [${res.error?.code}]: ${res.error?.message}`);
// Possible error codes:
// CONTRACT_NOT_FOUND -- address is not a contract on this chain
// FUNCTION_NOT_FOUND -- function name does not match the ABI
// EXECUTION_REVERTED -- the call reverted on-chain
// INVALID_ARGS -- wrong number or type of arguments
return;
}
console.log('Result:', res.data);
Using Outside React
In a Node.js or Edge runtime, instantiate the client directly:
import { OneEngineClient } from '@one_deploy/sdk';
const client = new OneEngineClient({
apiKey: process.env.ONE_API_KEY!,
projectId: process.env.ONE_PROJECT_ID!,
});
const res = await client.readContract({
contractAddress: '0xA0b8...3E7a',
chainId: 1,
functionName: 'totalSupply',
});
console.log('Total supply:', res.data);
Next Steps
- Write Contract -- send state-changing transactions.
- Deploy Contract -- deploy new contracts to any supported chain.
- Contracts Overview -- full method inventory.