> ## Documentation Index
> Fetch the complete documentation index at: https://developers.circle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart: Set up and transfer USDC on Starknet

This quickstart guide helps you write a standalone `index.js` script that checks
your USDC balance and sends a test transfer on the Starknet Sepolia. It's
designed for developers looking to quickly get hands-on with
[USDC](/stablecoins/what-is-usdc) on Starknet.

## Prerequisites

Before you begin, make sure you have:

* Installed [**Node.js v18+**](https://nodejs.org/) and `npm`, which comes with
  `Node.js`.
  * Created a free [**Alchemy account**](https://alchemy.com/starknet) to get an
    API key for Starknet RPC access.
* Created a Starknet Sepolia wallet:
  * [**Braavos wallet (Recommended)**](https://braavos.app/) - Best
    compatibility for programmatic transactions.

    Alternatives: [Argent X](https://www.argent.xyz/argent-x/) (Note:
    Guardian-protected accounts may require additional configuration).

  * [Request testnet STRK from the faucet](https://starknet-faucet.vercel.app/).

  * [Request testnet USDC from the faucet](https://faucet.circle.com/)

### USDC contract address

Use the following contract address for USDC on the Starknet Sepolia Testnet:

USDC contract:
[`0x0512feAc6339Ff7889822cb5aA2a86C848e9D392bB0E3E237C008674feeD8343`](https://sepolia.voyager.online/contract/0x053b40a647cedfca6ca84f542a0fe36736031905a9639a7f19a3c1e66bfd5080)

## Part 1: Set up your project

Follow these steps to install dependencies and set up your script environment.

### 1.1. Initialize a project

Create a new directory and initialize it with `npm`:

```bash theme={null}
mkdir usdc-starknet-script
cd usdc-starknet-script
npm init -y
npm pkg set type=module
```

### 1.2. Install required dependencies

Install `starknet` (version 8.x) and `dotenv`:

```bash theme={null}
npm install starknet@^8.9.0 dotenv
```

### 1.3. Create your `.env` file

In the project root, create a `.env` file and add the following values:

```text Text theme={null}
# Your Starknet account address (felt252 format with 0x prefix)
ACCOUNT_ADDRESS=0x<YOUR_ACCOUNT_ADDRESS>

# Your private key (felt252 format with 0x prefix)
PRIVATE_KEY=0x<YOUR_PRIVATE_KEY>

# The address you want to send USDC to (felt252 format with 0x prefix)
RECIPIENT_ADDRESS=0x<RECIPIENT_ADDRESS>
```

<Info>
  **Important:** On Starknet, you need both your account address and private key
  because Starknet uses [account
  abstraction](https://www.starknet.io/blog/account-abstraction). Your private
  key alone doesn't derive your account address.
</Info>

## Part 2: Build your script

Create a file named `index.js`. You'll build your script step-by-step in the
following sections.

### 2.1. Import libraries and define constants

In `index.js`, start by importing dependencies and setting up the chain and
token configuration:

```javascript theme={null}
import "dotenv/config";
import { Account, Contract, RpcProvider, uint256 } from "starknet";

const provider = new RpcProvider({
  nodeUrl:
    "https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_10/YOUR_API_KEY",
});

const USDC_ADDRESS =
  "0x053b40A647CEDfca6cA84f542A0fe36736031905A9639a7f19A3C1e66bFd5080";
const USDC_DECIMALS = 6;

const USDC_ABI = [
  {
    name: "balance_of",
    type: "function",
    inputs: [
      {
        name: "account",
        type: "core::starknet::contract_address::ContractAddress",
      },
    ],
    outputs: [{ name: "balance", type: "core::integer::u256" }],
    state_mutability: "view",
  },
  {
    name: "transfer",
    type: "function",
    inputs: [
      {
        name: "recipient",
        type: "core::starknet::contract_address::ContractAddress",
      },
      { name: "amount", type: "core::integer::u256" },
    ],
    outputs: [{ name: "success", type: "core::bool" }],
    state_mutability: "external",
  },
];
```

<Info>
  Replace `YOUR_API_KEY` with your Alchemy API key from
  [alchemy.com/starknet](https://alchemy.com/starknet)
</Info>

<Accordion title="Learn more: Why use a minimal ABI?" icon="circle-info">
  This ABI includes only the two methods needed for this script:

  * `balanceOf(address)` to check the token balance.
  * `transfer(to, amount)` to send USDC.

  This makes the ABI compact and easier to understand. Using a minimal ABI:

  * Reduces complexity by excluding unrelated functions.
  * Speeds up onboarding for new developers.
  * Avoids unnecessary contract data that would be unused in this context.

  <Info>
    **Note:** Starknet uses Cairo, so function names follow snake\_case convention
    (for example, `balance_of` instead of `balanceOf`).
  </Info>
</Accordion>

### 2.2. Set up Starknet account and contract

Set up the Starknet account and contract instances:

```javascript theme={null}
const account = new Account({
  provider,
  address: process.env.ACCOUNT_ADDRESS,
  signer: process.env.PRIVATE_KEY,
});

const usdcContract = new Contract({
  abi: USDC_ABI,
  address: USDC_ADDRESS,
  providerOrAccount: account,
});
```

<Accordion title="Learn more: account abstraction on Starknet" icon="circle-info">
  Unlike Ethereum, Starknet uses **account abstraction** by default:

  * Every wallet is a smart contract (not an EOA).
  * You need both the account address AND private key.
  * The private key signs transactions, but the account contract validates them.

  This enables features like:

  * Multi-signature wallets
  * Social recovery
  * Custom transaction validation logic
  * Gasless transactions (meta-transactions)
</Accordion>

### 2.3. Check balance and send USDC

Now add the logic to check your balance and send tokens:

```javascript theme={null}
(async () => {
  try {
    const balanceResult = await usdcContract.balance_of(account.address);
    const balance = uint256.uint256ToBN(balanceResult.balance);
    const balanceFormatted = Number(balance) / 10 ** USDC_DECIMALS;

    console.log("Sender:", account.address);
    console.log("Recipient:", process.env.RECIPIENT_ADDRESS);
    console.log("USDC balance:", balanceFormatted.toFixed(2));

    const amount = 0.1;
    const amountU256 = uint256.bnToUint256(amount * 10 ** USDC_DECIMALS);

    const tx = await usdcContract.transfer(
      process.env.RECIPIENT_ADDRESS,
      amountU256,
    );

    await provider.waitForTransaction(tx.transaction_hash);

    console.log("Transfer successful!");
    console.log("Tx hash:", tx.transaction_hash);
    console.log(
      "Explorer:",
      `https://sepolia.voyager.online/tx/${tx.transaction_hash}`,
    );
  } catch (err) {
    console.error("Transfer failed:", err.message || err);
    process.exit(1);
  }
})();
```

## Part 3: Run your script

To run your script, use the following command:

```bash theme={null}
node index.js
```

### Sample output

If the script runs successfully, your terminal will print a transaction summary
like this:

```text Text theme={null}
Sender: 0x025c0197095dff110edc45fd171c498b167fbe1c803294d22483064b0207a465
Recipient: 0x043ccE75C31169455E07B19265024107B067700BB711DEeffecE32766d7bf5c7
USDC balance: 10.00
Transfer successful!
Tx hash: 0xabc123def456789...
Explorer: https://sepolia.voyager.online/tx/0xabc123def456789...
```

You can open the explorer link in your browser to view the transaction on
Voyager.

## Additional notes

* **Testnet only:** This guide runs on the Starknet Sepolia testnet. Tokens and
  transfers here are not real and hold no value.
* **Security best practices:** Always store sensitive data like private keys in
  environment variables. Never hardcode or commit `.env` files to version
  control. Add `.env` to your `.gitignore` file.
* **Gas fees:** Starknet requires STRK tokens for gas. Be sure to request
  testnet STRK from the faucet so your transactions can be processed.
* **Lightweight ABI:** The ABI used here is minimal. It includes only the
  functions necessary for balance checks and transfers, which keeps the script
  lean.
* **V3 transactions:** Starknet.js v8 uses V3 transactions by default, which
  include resource bounds for L1 gas, L2 gas, and L1 data gas.
* **Wallet compatibility:** Braavos wallet is recommended for programmatic
  transactions. Argent accounts with guardians may require additional
  configuration.
