Skip to main content
starknet-js Reference for building Starknet applications using starknet.js v9.x SDK, including contract interaction, account management, transaction handling, fee estimation, wallet integration, and paymaster flows.
Aller à l'installation Skills Marketplace Découvrez et explorez les compétences IA créées par la communauté.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Copier le promptAfficher les détails du prompt Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
npx skills add https://github.com/keep-starknet-strange/starknet-agentic --skill starknet-jsLa commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Télécharger Zip Téléchargement... Explorateur de fichiers
9 fichiers Plus depuis ce dépôt Routes Starknet agent, wallet, DeFi, identity, SDK, and Cairo contract work to the smallest focused skill module.
SNIP-36 virtual block proving on Starknet. Trigger on "virtual block", "SNIP-36", "off-chain proof", "anonymous vote", "heavy computation off-chain", "prove a transaction". Covers Cairo virtual contract, proof server, starknet.js integration, and on-chain verification.
Security audit of Cairo/Starknet code. Trigger on "audit", "check this contract", "review for security". Modes - default (full repo), deep (+ adversarial reasoning), or specific filenames.
Métiers associés SOC
Basé sur la classification professionnelle SOC
name starknet-js description Reference for building Starknet applications using starknet.js v9.x SDK, including contract interaction, account management, transaction handling, fee estimation, wallet integration, and paymaster flows. license Apache-2.0 metadata {"author":"0xlny","version":"1.0.0","org":"keep-starknet-strange"} compatibility Node.js 18+, TypeScript 5+, npm package: starknet@^9.0.0 keywords ["starknet","starknet-js","sdk","typescript","smart-contracts","account-abstraction","paymaster","multicall","snip-9","snip-12","erc-20","erc-721","wallet","rpc","fee-estimation"] allowed-tools ["Bash","Read","Write","Glob","Grep","Task"] user-invocable true
starknet.js v9.x SDK
Related modules: skills catalog .
When to Use
Building Starknet apps with provider, account, contract, wallet, or paymaster flows.
When NOT to Use
Cairo contract authoring, deployment-only runbooks, or security audits.
Quick Start
npm install starknet
Minimal setup to read from Starknet:
import { RpcProvider , Contract } from 'starknet' ;
const provider = await RpcProvider .create ({ nodeUrl : 'https://rpc.starknet.lava.build' });
const contract = new Contract (abi, contractAddress, provider);
const result = await contract.get_balance ();
Core Architecture
Provider -> Account -> Contract
| | |
Network Identity Interaction
Provider : Read-only network connection (RpcProvider)
Account : Extends Provider with signing and transaction capabilities
Contract : Type-safe interface to deployed contracts
Use Provider for read operations, Account for write operations.
Provider Setup
import { RpcProvider } from 'starknet' ;
const provider = await RpcProvider .create ({
nodeUrl : 'https://rpc.starknet.lava.build'
});
Mainnet: https://rpc.starknet.lava.build
Sepolia: https://rpc.starknet-testnet.lava.build
const chainId = await provider.getChainId ();
const block = await provider.getBlock ('latest' );
const nonce = await provider.getNonceForAddress (accountAddress);
await provider.waitForTransaction (txHash);
const value = await provider.getStorageAt (contractAddress, storageKey);
Account Management
Account Creation (4 Steps) import { hash, ec, encode, CallData } from 'starknet' ;
const privateKey = '0x' + encode.buf2hex (ec.starkCurve .utils .randomPrivateKey ());
const publicKey = ec.starkCurve .getStarkKey (privateKey);
const classHash = '0x540d7f5ec7ecf317e68d48564934cb99259781b1ee3cedbbc37ec5337f8e688' ;
const constructorCalldata = CallData .compile ({ publicKey });
const address = hash.calculateContractAddressFromHash (publicKey, classHash, constructorCalldata, 0 );
Step 2: Fund the address with STRK before deployment.
import { Account } from 'starknet' ;
const account = new Account ({ provider, address, signer : privateKey, cairoVersion : '1' });
const { transaction_hash } = await account.deployAccount ({
classHash,
constructorCalldata,
addressSalt : publicKey
});
await provider.waitForTransaction (transaction_hash);
Step 4: Use the account for transactions.
Connect to Existing Account const account = new Account ({
provider,
address : '0x123...' ,
signer : privateKey,
cairoVersion : '1'
});
Contract Interaction
Connect to Contract import { Contract } from 'starknet' ;
const contract = new Contract (abi, contractAddress, provider);
const writeContract = new Contract (abi, contractAddress, account);
Typed Contract (Type-Safe)
const typedContract = contract.typedv2 (abi);
const balance = await typedContract.balanceOf (userAddress);
Read State const balance = await contract.get_balance ();
const userBalance = await contract.balanceOf (userAddress);
Write (Execute) const tx = await contract.increase_balance (100 );
await provider.waitForTransaction (tx.transaction_hash );
Multicall (Batch Transactions) import { CallData , cairo } from 'starknet' ;
const calls = [
{
contractAddress : tokenAddress,
entrypoint : 'approve' ,
calldata : CallData .compile ({ spender : bridgeAddress, amount : cairo.uint256 (1000n ) })
},
{
contractAddress : bridgeAddress,
entrypoint : 'deposit' ,
calldata : CallData .compile ({ amount : cairo.uint256 (1000n ) })
}
];
const tx = await account.execute (calls);
Using populate() for type-safety:
const approveCall = tokenContract.populate ('approve' , {
spender : bridgeAddress,
amount : cairo.uint256 (1000n )
});
const depositCall = bridgeContract.populate ('deposit' , { amount : cairo.uint256 (1000n ) });
const tx = await account.execute ([approveCall, depositCall]);
Parse Events const receipt = await provider.getTransactionReceipt (txHash);
const events = contract.parseEvents (receipt);
const transferEvents = contract.parseEvents (receipt, 'Transfer' );
Transaction Simulation Simulate before executing to catch reverts and inspect state changes:
const simResult = await account.simulateTransaction (
[{ type : 'INVOKE' , payload : calls }],
{ skipValidate : false }
);
console .log ('Fee estimate:' , simResult[0 ].fee_estimation );
console .log ('Trace:' , simResult[0 ].transaction_trace );
const trace = simResult[0 ].transaction_trace ;
if (trace?.state_diff ) {
console .log ('Storage changes:' , trace.state_diff .storage_diffs );
}
Fee Estimation const fee = await account.estimateInvokeFee (calls);
console .log ({
overallFee : fee.overall_fee ,
resourceBounds : fee.resourceBounds
});
Execute with custom bounds:
const tx = await account.execute (calls, {
resourceBounds : {
l1_gas : { amount : '0x2000' , price : '0x1000000000' },
l2_gas : { amount : '0x0' , price : '0x0' },
l1_data_gas : { amount : '0x1000' , price : '0x1000000000' }
}
});
const tipStats = await provider.getEstimateTip ();
const tx = await account.execute (calls, { tip : tipStats.percentile_75 });
Transaction Receipt Handling const receipt = await provider.waitForTransaction (txHash);
if (receipt.isSuccess ()) {
console .log ('Transaction succeeded' );
} else if (receipt.isReverted ()) {
console .log ('Reverted:' , receipt.revert_reason );
} else if (receipt.isRejected ()) {
console .log ('Rejected' );
} else if (receipt.isError ()) {
console .log ('Error' );
}
Wallet Integration Connect to browser wallets (ArgentX, Braavos):
import { connect } from '@starknet-io/get-starknet' ;
import { WalletAccount } from 'starknet' ;
const selectedWallet = await connect ({ modalMode : 'alwaysAsk' });
const walletAccount = await WalletAccount .connect (
{ nodeUrl : 'https://rpc.starknet.lava.build' },
selectedWallet
);
const tx = await walletAccount.execute (calls);
walletAccount.onAccountChange ((accounts ) => console .log ('New account:' , accounts[0 ]));
walletAccount.onNetworkChanged ((chainId ) => console .log ('Network changed:' , chainId));
Paymaster (Gas Sponsorship) Setup paymaster for sponsored or alternative gas token transactions:
import { PaymasterRpc , Account } from 'starknet' ;
const paymaster = new PaymasterRpc ({ nodeUrl : 'https://sepolia.paymaster.avnu.fi' });
const account = new Account ({ provider, address, signer : privateKey, paymaster });
Sponsored (dApp pays gas):
const tx = await account.executePaymasterTransaction (calls, { feeMode : { mode : 'sponsored' } });
Alternative token (e.g., USDC):
const tokens = await account.paymaster .getSupportedTokens ();
const feeDetails = { feeMode : { mode : 'default' , gasToken : USDC_ADDRESS } };
const estimate = await account.estimatePaymasterTransactionFee (calls, feeDetails);
const tx = await account.executePaymasterTransaction (calls, feeDetails, estimate.suggested_max_fee_in_gas_token );
Message Signing (SNIP-12) const typedData = {
types : {
StarknetDomain : [
{ name : 'name' , type : 'shortstring' },
{ name : 'version' , type : 'shortstring' },
{ name : 'chainId' , type : 'shortstring' },
{ name : 'revision' , type : 'shortstring' }
],
Message : [{ name : 'content' , type : 'shortstring' }]
},
primaryType : 'Message' ,
domain : { name : 'MyDapp' , version : '1' , chainId : 'SN_SEPOLIA' , revision : '1' },
message : { content : 'Hello Starknet' }
};
const signature = await account.signMessage (typedData);
const msgHash = await account.hashMessage (typedData);
const isValid = ec.starkCurve .verify (signature, msgHash, publicKey);
CallData & Cairo Types import { CallData , cairo, CairoCustomEnum , CairoOption , CairoOptionVariant } from 'starknet' ;
const calldata = new CallData (abi);
const compiled = calldata.compile ('transfer' , { recipient : '0x...' , amount : cairo.uint256 (1000n ) });
cairo.uint256 (1000n )
cairo.felt252 (1000 )
cairo.felt ('0x123' )
cairo.bool (true )
cairo.byteArray ('Hello' )
import { shortString } from 'starknet' ;
shortString.encodeShortString ('hello' )
shortString.decodeShortString ('0x...' )
const myEnum = new CairoCustomEnum ({ Variant1 : { value : 123 } });
const some = new CairoOption (CairoOptionVariant .Some , value);
Important: Always use BigInt (e.g., 1000n) for token amounts and balances. Never use Number() or parseFloat() on wei values -- JavaScript numbers lose precision above 2^53.
ERC-20 Token Operations const erc20 = new Contract (erc20Abi, tokenAddress, account);
const balance = await erc20.balanceOf (account.address );
console .log ('Balance (wei):' , balance.toString ());
const amount = cairo.uint256 (1000000000000000000n );
const tx = await erc20.transfer (recipientAddress, amount);
await provider.waitForTransaction (tx.transaction_hash );
await erc20.approve (spenderAddress, cairo.uint256 (amount));
Utility Functions import { stark, ec, encode, num, hash } from 'starknet' ;
const privateKey = '0x' + encode.buf2hex (ec.starkCurve .utils .randomPrivateKey ());
const publicKey = ec.starkCurve .getStarkKey (privateKey);
num.toHex (123 );
num.toBigInt ('0x7b' );
hash.getSelectorFromName ('transfer' );
hash.calculateContractAddressFromHash (salt, classHash, calldata, deployer);
Contract Deployment
const { transaction_hash, contract_address } = await account.deploy ({
classHash : '0x...' ,
constructorCalldata : CallData .compile ({ owner : account.address }),
salt : stark.randomAddress (),
unique : true
});
const declareResponse = await account.declare ({
contract : compiledSierra,
casm : compiledCasm
});
await provider.waitForTransaction (declareResponse.transaction_hash );
const deployResponse = await account.deploy ({
classHash : declareResponse.class_hash ,
constructorCalldata : CallData .compile ({ owner : account.address })
});
const result = await account.declareAndDeploy ({
contract : compiledContract,
casm : compiledCasm,
constructorCalldata : CallData .compile ({ owner : account.address })
});
Outside Execution (SNIP-9) Execute transactions on behalf of another account (gasless/delegated):
const version = await account.getSnip9Version ();
const outsideTransaction = await account.getOutsideTransaction (
{ caller : executorAddress, execute_after : now, execute_before : now + 3600 },
calls,
'V2'
);
const result = await executorAccount.executeFromOutside (outsideTransaction);
Error Handling import { LibraryError , RpcError } from 'starknet' ;
try {
const tx = await account.execute (calls);
} catch (error) {
if (error instanceof RpcError ) {
console .error ('RPC error:' , error.code , error.message );
} else if (error instanceof LibraryError ) {
console .error ('Library error:' , error.message );
}
}
Logging & Configuration import { config, setLogLevel } from 'starknet' ;
config.set ('transactionVersion' , '0x3' );
config.get ('transactionVersion' );
setLogLevel ('DEBUG' );