$npx -y skills add keep-starknet-strange/starknet-agentic --skill starknet-jsReference for building Starknet applications using starknet.js v9.x SDK, including contract interaction, account management, transaction handling, fee estimation, wallet integration, and paymaster flows.
| 1 | # starknet.js v9.x SDK |
| 2 | |
| 3 | Related modules: [skills catalog](../README.md). |
| 4 | |
| 5 | ## When to Use |
| 6 | |
| 7 | - Building Starknet apps with provider, account, contract, wallet, or paymaster flows. |
| 8 | |
| 9 | ## When NOT to Use |
| 10 | |
| 11 | - Cairo contract authoring, deployment-only runbooks, or security audits. |
| 12 | |
| 13 | ## Quick Start |
| 14 | |
| 15 | ```bash |
| 16 | npm install starknet |
| 17 | ``` |
| 18 | |
| 19 | Minimal setup to read from Starknet: |
| 20 | |
| 21 | ```typescript |
| 22 | import { RpcProvider, Contract } from 'starknet'; |
| 23 | |
| 24 | const provider = await RpcProvider.create({ nodeUrl: 'https://rpc.starknet.lava.build' }); |
| 25 | const contract = new Contract(abi, contractAddress, provider); |
| 26 | const result = await contract.get_balance(); |
| 27 | ``` |
| 28 | |
| 29 | ## Core Architecture |
| 30 | |
| 31 | ``` |
| 32 | Provider -> Account -> Contract |
| 33 | | | | |
| 34 | Network Identity Interaction |
| 35 | ``` |
| 36 | |
| 37 | - **Provider**: Read-only network connection (RpcProvider) |
| 38 | - **Account**: Extends Provider with signing and transaction capabilities |
| 39 | - **Contract**: Type-safe interface to deployed contracts |
| 40 | |
| 41 | Use Provider for read operations, Account for write operations. |
| 42 | |
| 43 | ## Provider Setup |
| 44 | |
| 45 | ```typescript |
| 46 | import { RpcProvider } from 'starknet'; |
| 47 | |
| 48 | // Recommended: Auto-detect RPC spec version |
| 49 | const provider = await RpcProvider.create({ |
| 50 | nodeUrl: 'https://rpc.starknet.lava.build' |
| 51 | }); |
| 52 | ``` |
| 53 | |
| 54 | **Networks:** |
| 55 | - Mainnet: `https://rpc.starknet.lava.build` |
| 56 | - Sepolia: `https://rpc.starknet-testnet.lava.build` |
| 57 | |
| 58 | **Key Methods:** |
| 59 | ```typescript |
| 60 | const chainId = await provider.getChainId(); |
| 61 | const block = await provider.getBlock('latest'); |
| 62 | const nonce = await provider.getNonceForAddress(accountAddress); |
| 63 | await provider.waitForTransaction(txHash); |
| 64 | |
| 65 | // Read storage directly |
| 66 | const value = await provider.getStorageAt(contractAddress, storageKey); |
| 67 | ``` |
| 68 | |
| 69 | ## Account Management |
| 70 | |
| 71 | ### Account Creation (4 Steps) |
| 72 | |
| 73 | **Step 1: Compute address** |
| 74 | ```typescript |
| 75 | import { hash, ec, encode, CallData } from 'starknet'; |
| 76 | |
| 77 | // IMPORTANT: `stark.randomAddress()` returns an address-like random felt and is NOT a private key. |
| 78 | // Use a real stark curve private key generator. |
| 79 | const privateKey = '0x' + encode.buf2hex(ec.starkCurve.utils.randomPrivateKey()); |
| 80 | const publicKey = ec.starkCurve.getStarkKey(privateKey); |
| 81 | |
| 82 | // NOTE: account class hashes are network/account-type dependent. |
| 83 | // Treat this as an example only (verify the correct class hash for your setup). |
| 84 | const classHash = '0x540d7f5ec7ecf317e68d48564934cb99259781b1ee3cedbbc37ec5337f8e688'; // example |
| 85 | |
| 86 | const constructorCalldata = CallData.compile({ publicKey }); |
| 87 | const address = hash.calculateContractAddressFromHash(publicKey, classHash, constructorCalldata, 0); |
| 88 | ``` |
| 89 | |
| 90 | **Step 2: Fund the address** with STRK before deployment. |
| 91 | |
| 92 | **Step 3: Deploy** |
| 93 | ```typescript |
| 94 | import { Account } from 'starknet'; |
| 95 | |
| 96 | // NOTE: Account constructor signature varies across starknet.js versions. |
| 97 | // If this doesn't typecheck for your version, refer to the official docs. |
| 98 | const account = new Account({ provider, address, signer: privateKey, cairoVersion: '1' }); |
| 99 | const { transaction_hash } = await account.deployAccount({ |
| 100 | classHash, |
| 101 | constructorCalldata, |
| 102 | addressSalt: publicKey |
| 103 | }); |
| 104 | await provider.waitForTransaction(transaction_hash); |
| 105 | ``` |
| 106 | |
| 107 | **Step 4: Use the account** for transactions. |
| 108 | |
| 109 | ### Connect to Existing Account |
| 110 | |
| 111 | ```typescript |
| 112 | const account = new Account({ |
| 113 | provider, |
| 114 | address: '0x123...', |
| 115 | signer: privateKey, |
| 116 | cairoVersion: '1' // Optional, auto-detected if omitted |
| 117 | }); |
| 118 | ``` |
| 119 | |
| 120 | ## Contract Interaction |
| 121 | |
| 122 | ### Connect to Contract |
| 123 | |
| 124 | ```typescript |
| 125 | import { Contract } from 'starknet'; |
| 126 | |
| 127 | const contract = new Contract(abi, contractAddress, provider); // Read-only |
| 128 | const writeContract = new Contract(abi, contractAddress, account); // Read-write |
| 129 | ``` |
| 130 | |
| 131 | ### Typed Contract (Type-Safe) |
| 132 | |
| 133 | ```typescript |
| 134 | // Get full TypeScript autocomplete and type checking from ABI |
| 135 | const typedContract = contract.typedv2(abi); |
| 136 | const balance = await typedContract.balanceOf(userAddress); |
| 137 | ``` |
| 138 | |
| 139 | ### Read State |
| 140 | |
| 141 | ```typescript |
| 142 | const balance = await contract.get_balance(); |
| 143 | const userBalance = await contract.balanceOf(userAddress); |
| 144 | ``` |
| 145 | |
| 146 | ### Write (Execute) |
| 147 | |
| 148 | ```typescript |
| 149 | const tx = await contract.increase_balance(100); |
| 150 | await provider.waitForTransaction(tx.transaction_hash); |
| 151 | ``` |
| 152 | |
| 153 | ### Multicall (Batch Transactions) |
| 154 | |
| 155 | ```typescript |
| 156 | import { CallData, cairo } from 'starknet'; |
| 157 | |
| 158 | const calls = [ |
| 159 | { |
| 160 | contractAddress: tokenAddress, |
| 161 | entrypoint: 'approve |