Interact with your contract
Once your contract is connected (see Contract Instance guide), you can interact with it:
- Read operations: Free - query contract state without fees
- Write operations: Paid - modify contract state with STRK fees
Ensure your account has sufficient STRK for transaction fees (20 STRK is a good start).
Here we will interact with a test.cairo
contract (Cairo 1) already deployed in Sepolia Testnet at the address:
This contract contains a storage variable called balance
.
- It can be read with the
fn get_balance(self: @TContractState) -> felt252;
- Balance can be modified with
fn increase_balance(ref self: TContractState, amount: felt252);
import { Contract, CallData } from 'starknet';
🔍 Reading Contract State
Use the contract instance (connected with Provider) to call view functions:
// Assuming contract is already connected (see connect_contract.md)
const balance = await myContract.get_balance();
console.log('Balance:', balance);
// View functions with parameters
const userBalance = await myContract.balanceOf(userAddress);
console.log('User balance:', userBalance);
- Cairo 1 contracts return values directly as
bigint
- Cairo 0 contracts return objects with named properties (e.g.,
result.res
) :::
✍️ Writing to Contract State
Use the contract instance (connected with Account) to call state-changing functions:
// Assuming contract is connected with Account (see connect_contract.md)
// Direct function call
const tx = await myContract.increase_balance(10);
await myProvider.waitForTransaction(tx.transaction_hash);
// Using populate for complex parameters
const call = myContract.populate('transfer', {
recipient: recipientAddress,
amount: transferAmount,
});
const tx2 = await myContract.transfer(call.calldata);
await myProvider.waitForTransaction(tx2.transaction_hash);
Use Contract.populate()
to prepare call data for complex parameters or multicalls.
:::
v8 Note: Only V3 transactions with STRK fees are supported in Starknet.js v8. ETH fee transactions (V1/V2) have been removed with Starknet 0.14.
All transactions now use V3 transactions with STRK fees by default.
✍️ Send a transaction, paying fees with ETH or any supported Token
Check Account Paymaster Section.
Sending sequential transactions
If you intend to send sequential transactions through the contract object, like so:
const tx = await cairo1Contract.array2d_ex(data);
const tx1 = await cairo1Contract.array2d_ex(data);
Be sure to use waitForTransaction
between the calls, because you may experience issues with the nonce not incrementing. For more details about multicalls, see this guide.
For more information about defining call messages and parameters, see this guide.
Multiple Operations (Multicall)
Execute multiple contract calls in a single transaction:
const result = await myAccount.execute([
{
contractAddress: tokenAddress,
entrypoint: 'approve',
calldata: CallData.compile({ spender: recipient, amount: 1000n }),
},
{
contractAddress: tokenAddress,
entrypoint: 'transfer',
calldata: CallData.compile({ recipient, amount: 500n }),
},
]);
await myProvider.waitForTransaction(result.transaction_hash);
For detailed multicall examples, see the Multicall guide.
Other existing methods
Some other useful methods to interact with Starknet:
Function name defined in the code
If you want to call a function with its name contained in a variable:
const listFn = ['calc-sum', 'calc-hash', 'calc-proof'];
// fnChoice is a number defined during execution
const res = await myTestContract[listFn[fnChoice]](200, 234567897n, 865423);
Light and fast call
If you want to have a very fast execution, with minimum resource usage:
const specialParameters: Calldata = ['2036735872918048433518', '5130580', '18'];
const getResponse = await myAccount.call('get_bal', specialParameters, { parseRequest: false });
You provide the low-level numbers expected by Starknet, without any parsing or checking. See more details here.
Transaction receipt response
You can interpret the transaction receipt response to check whether it succeeded or not.
const result = await myAccount.execute(myCall);
const txR = await myProvider.waitForTransaction(result.transaction_hash);
console.log(txR.statusReceipt, txR.value);
console.log(txR.isSuccess(), txR.isReverted(), txR.isError());
txR.match({
success: () => {
console.log('Success');
},
_: () => {
console.log('Unsuccess');
},
});
txR.match({
success: (txR: SuccessfulTransactionReceiptResponse) => {
console.log('Success =', txR);
},
reverted: (txR: RevertedTransactionReceiptResponse) => {
console.log('Reverted =', txR);
},
error: (err: Error) => {
console.log('An error occured =', err);
},
});