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.
Install / Use
npx skills add internet-court/internet-court-skill --skill starknet-jsInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
LegalSupported Platforms
Tags
Our assessment of starknet-js
starknet-js scores 96/100 on our quality scale, 12th of 104 Legal skills we index (top 12%).
Its SKILL.md is 13 KB long, well organised into 29 sections with 32 code examples: a thorough specification that gives an agent plenty to work with.
With 6,129 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated 39 days ago, so starknet-js is actively maintained.
- No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
- Its trust signals score 88/100, with 1 caution from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
starknet-js compared with similar skills
All 4 of these similar skills score higher than starknet-js; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| starknet-js (this skill)by internet-court | 96 | 6.1k | 39d ago | SKILL.md |
| headroomby headroomlabs-ai | 100 | 74.0k | 1d ago | CLAUDE.md |
| rufloby ruvnet | 100 | 73.4k | today | CLAUDE.md |
| algorithmic-artby anthropics | 100 | 177.9k | 5d ago | SKILL.md |
| pptxby anthropics | 100 | 177.9k | 5d ago | SKILL.md |
Frequently asked questions
- How do I install starknet-js?
- Run
npx skills add internet-court/internet-court-skill --skill starknet-js. The install tabs above show the steps for each supported agent. - Which AI agents does starknet-js work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is starknet-js safe to use?
- It declares no license and scores 88/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is starknet-js still maintained?
- The repository was last updated 39 days ago, so starknet-js is actively maintained.
Skill content
View source on GitHubname: 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';
// Recommended: Auto-detect RPC spec version
const provider = await RpcProvider.create({
nodeUrl: 'https://rpc.starknet.lava.build'
});
Networks:
- Mainnet:
https://rpc.starknet.lava.build - Sepolia:
https://rpc.starknet-testnet.lava.build
Key Methods:
const chainId = await provider.getChainId();
const block = await provider.getBlock('latest');
const nonce = await provider.getNonceForAddress(accountAddress);
await provider.waitForTransaction(txHash);
// Read storage directly
const value = await provider.getStorageAt(contractAddress, storageKey);
Account Management
Account Creation (4 Steps)
Step 1: Compute address
import { hash, ec, encode, CallData } from 'starknet';
// IMPORTANT: `stark.randomAddress()` returns an address-like random felt and is NOT a private key.
// Use a real stark curve private key generator.
const privateKey = '0x' + encode.buf2hex(ec.starkCurve.utils.randomPrivateKey());
const publicKey = ec.starkCurve.getStarkKey(privateKey);
// NOTE: account class hashes are network/account-type dependent.
// Treat this as an example only (verify the correct class hash for your setup).
const classHash = '0x540d7f5ec7ecf317e68d48564934cb99259781b1ee3cedbbc37ec5337f8e688'; // example
const constructorCalldata = CallData.compile({ publicKey });
const address = hash.calculateContractAddressFromHash(publicKey, classHash, constructorCalldata, 0);
Step 2: Fund the address with STRK before deployment.
Step 3: Deploy
import { Account } from 'starknet';
// NOTE: Account constructor signature varies across starknet.js versions.
// If this doesn't typecheck for your version, refer to the official docs.
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' // Optional, auto-detected if omitted
});
Contract Interaction
Connect to Contract
import { Contract } from 'starknet';
const contract = new Contract(abi, contractAddress, provider); // Read-only
const writeContract = new Contract(abi, contractAddress, account); // Read-write
Typed Contract (Type-Safe)
// Get full TypeScript autocomplete and type checking from ABI
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);
// Check state changes before execution
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 // V3: l1_gas, l2_gas, l1_data_gas
});
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' }
}
});
With priority tip:
const tipStats = await provider.getEstimateTip();
const tx = await account.execute(calls, { tip: tipStats.percentile_75 });
Transaction Receipt Handling
const receipt = await provider.waitForTransaction(txHash);
// Status check helpers
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
);
// Use like regular Account
const tx = await walletAccount.execute(calls);
// Event handlers
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';
// Compile with ABI
const calldata = new CallData(abi);
const compiled = calldata.compile('transfer', { recipient: '0x...', amount: cairo.uint256(1000n) });
// Cairo type helpers - always use BigInt (n suffix) for token amounts
cairo.uint256(1000n) // { low, high } - ALWAYS use BigInt for precision
cairo.felt252(1000) // BigInt
cairo.felt('0x123') // hex to felt
cairo.bool(true) // Cairo bool
cairo.byteArray('Hello') // ByteArray for long strings
// Short strings (<= 31 chars)
import { shortString } from 'starknet';
shortString.encodeShortString('hello') // felt252
shortString.decodeShortString('0x...') // 'hello'
// Enums and Options
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);
// Read balance (returns BigInt - do NOT convert with Number())
const balance = await erc20.balanceOf(account.address);
console.log('Balance (wei):', balance.toString());
// Transfer (use BigInt for amount)
const amount = cairo.uint256(1000000000000000000n); // 1 token (18 decimals)
const tx = await erc20.transfer(recipientAddress, amount);
await provider.waitForTransaction(tx.transaction_hash);
// Approve + transferFrom pattern
await erc20.approve(spenderAddress, cairo.uint256(amount));
Utility Functions
import { stark, ec, encode, num, hash } from 'starknet';
// Key generation
const privateKey = '0x' + encode.buf2hex(ec.starkCurve.utils.randomPrivateKey());
const publicKey = ec.starkCurve.getStarkKey(privateKey);
// Number conversions
num.toHex(123); // '0x7b'
num.toBigInt('0x7b'); // 123n
// Hashing
hash.getSelectorFromName('transfer');
hash.calculateContractAddressFromHash(salt, classHash, calldata, deployer);
Contract Deployment
// Deploy via UDC
const { transaction_hash, contract_address } = await account.deploy({
classHash: '0x..
Truncated for display — read the full file on GitHub.
Related Skills
headroom
74.0kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
ruflo
73.4k🌊 The original agent harness. Deploy intelligent multi-player swarms, coordinate autonomous workflows, and build conversational AI systems. Features adaptive memory, self-learning intelligence, federation, vector RAG integration, and native Claude Code / Codex / Hermes and many more Integrated
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
pptx
177.9kUse this skill any time a .pptx or .potx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx or .potx file (even if the extracted content will be used elsewhere, like in an em…
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
