본문으로 건너뛰기
cccskills
무료GitHub에 공개

starknet-js

Develop Starknet apps with starknet.js v9.x using examples for contract calls, account management, wallet connections, and transaction handling. It also covers transaction simulation, fee estimates, and paymasters, services that sponsor fees or accept alternative tokens.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

원문원문 설명 보기

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.

실행 점수 미검증

설치 방법 보기

이럴 때 유용합니다

  • Reading and updating Starknet smart contracts
  • Connecting ArgentX or Braavos wallets
  • Simulating transactions and estimating fees before submission
  • Adding sponsored fees or payment with alternative tokens
  • Combining multiple contract calls into one transaction

포함된 파일(10)

  • SKILL.md13.5 KB
  • agents/openai.yaml328 B
  • LICENSE1.1 KB
  • package.json336 B
  • references/account-lifecycle.md1.2 KB
  • references/fee-strategy.md1.1 KB
  • references/provider-hardening.md1.1 KB
  • references/README.md413 B
  • scripts/account-example.ts1.0 KB
  • tsconfig.json248 B

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

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...',
  constructorCalldata: CallData.compile({ owner: account.address }),
  salt: stark.randomAddress(), // random felt252 salt (not a private key)
  unique: true
});

// Declare first, then deploy
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 })
});

// Or combined
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();  // 'V1' | 'V2' | 'UNSUPPORTED'

const outsideTransaction = await account.getOutsideTransaction(
  { caller: executorAddress, execute_after: now, execute_before: now + 3600 },
  calls,
  'V2'
);

// Executor submits the pre-signed transaction
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';

// Global config
config.set('transactionVersion', '0x3');
config.get('transactionVersion');

// Logging
setLogLevel('DEBUG');  // ERROR | WARN | INFO | DEBUG

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Build chat, image generation, and speech transcription features on 0G Compute Network, a distributed GPU marketplace. This skill guides SDK integration, model fine-tuning, response processing for billing, and account funding through code patterns and CLI commands.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Integrating chat and image generation into an application
  • Preparing model fine-tuning jobs
  • Checking balances and funding provider accounts
internet-court/internet-court-skill7천2026년 8월 20일 업데이트

Build servers and clients for A2A, an open protocol that lets AI agents communicate across frameworks. Publish agent capabilities, exchange tasks and results, stream progress, and add notifications for workflows involving multiple agents.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Connect agents built with different frameworks
  • Publish agent capabilities through an Agent Card
  • Build a research, writing, and review workflow
internet-court/internet-court-skill7천2026년 8월 20일 업데이트

Give an AI agent a wallet with administrator-defined transaction limits. The skill covers encrypted key storage, balance checks, and sending funds through code-enforced rules for destinations, amounts, transaction frequency, and emergency shutdown.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Give an agent a wallet with transaction limits
  • Restrict transfers to approved chains and addresses
  • Check balances and active rules before sending
internet-court/internet-court-skill7천2026년 8월 20일 업데이트

Manage a crypto wallet with the awal CLI, including sign-in, balance checks, transfers, swaps, and funding. Also find and pay for APIs through x402, a payment protocol, set up paid endpoints, and query blockchain data on Base.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Check wallet balances across supported networks
  • Send tokens to an address or ENS name
  • Swap tokens or add wallet funds
internet-court/internet-court-skill7천2026년 8월 20일 업데이트

Write TypeScript, Rust, or Python code for Alkahest escrow contracts, which hold assets until conditions are met. Covers creating escrows, submitting fulfillment, collecting payments, and building custom contracts that decide whether requirements have been satisfied.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Integrate Alkahest escrow into an application
  • Build a bot that creates escrows and submits fulfillment
  • Implement payment collection and fulfillment monitoring
internet-court/internet-court-skill7천2026년 8월 20일 업데이트

Use the Alkahest CLI to manage escrow, where assets are held until agreed conditions are met. It covers buyer deposits, seller fulfillment and collection, third-party decisions, token swaps, and reclaiming expired, unfulfilled deposits.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Creating escrow with release conditions
  • Submitting work and collecting escrowed assets
  • Approving or rejecting fulfillment as an oracle
internet-court/internet-court-skill7천2026년 8월 20일 업데이트

internet-court의 스킬 모두 보기

이 스킬의 문제 신고