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.
Ir a la instalación Skills Marketplace Descubre y explora habilidades de IA creadas por la comunidad.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Copiar promptMostrar detalles del prompt Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/keep-starknet-strange/starknet-agentic --skill starknet-jsEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Descargar Zip Descargando... Más de este repositorio 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.
Explorador de archivos
9 archivos Ocupaciones relacionadas SOC
Basado en la clasificación ocupacional 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' );