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

# Erc20

> Typed ERC20 contract wrapper that returns Amount objects for balances and allowances.

<Warning>
  `@chipi-stack/core` is in development (v0.1.0). APIs may change before stable release.
</Warning>

## Overview

`Erc20` provides a typed wrapper around ERC20 contract interactions on StarkNet. Read methods (`balanceOf`, `allowance`) return `Amount` objects. Write methods (`approveCall`, `transferCall`) return `Call` objects for use with `TxBuilder` or `Account.execute()`.

## Usage

```typescript theme={null}
import { Erc20, Amount, TokenRegistry } from "@chipi-stack/core";

const registry = new TokenRegistry("mainnet");
const usdcInfo = registry.bySymbol("USDC")!;
const usdc = new Erc20(usdcInfo, account);

// Query balance (returns Amount)
const balance = await usdc.balanceOf(myAddress);
console.log(balance.toFormatted()); // "150.5 USDC"
```

## Constructor

```typescript theme={null}
new Erc20(token: TokenInfo, account: Account)
```

### Parameters

* `token` (TokenInfo): Object with `symbol`, `decimals`, and `address`
* `account` (Account): A starknet.js `Account` instance

## Methods

### `balanceOf(address)`

Query the ERC20 balance of an address.

```typescript theme={null}
const balance = await usdc.balanceOf("0x123...");
console.log(balance.toFormatted()); // "1500.0 USDC"
console.log(balance.toBase());      // 1500000000n
```

#### Parameters

* `address` (string): StarkNet address to query

#### Returns

`Promise<Amount>`: The balance as an Amount object

### `allowance(owner, spender)`

Query the allowance granted by `owner` to `spender`.

```typescript theme={null}
const allowed = await usdc.allowance(ownerAddress, spenderAddress);
if (allowed.lt(transferAmount)) {
  console.log("Need to approve more tokens");
}
```

#### Parameters

* `owner` (string): Token owner address
* `spender` (string): Approved spender address

#### Returns

`Promise<Amount>`: The allowance as an Amount object

### `approveCall(spender, amount)`

Build an ERC20 approve Call object. Does not execute the transaction.

```typescript theme={null}
const call = usdc.approveCall(spenderAddress, amount);
// Use with TxBuilder
await new TxBuilder(account).add(call).send();
```

#### Parameters

* `spender` (string): Address to approve
* `amount` (Amount): Amount to approve

#### Returns

`Call`: A StarkNet Call object for use with TxBuilder or Account.execute()

#### Throws

* If `amount.decimals` doesn't match the token's decimals
* If `amount.symbol` doesn't match the token's symbol (when set)

### `transferCall(recipient, amount)`

Build an ERC20 transfer Call object. Does not execute the transaction.

```typescript theme={null}
const call = usdc.transferCall(recipientAddress, amount);
await new TxBuilder(account).add(call).send();
```

#### Parameters

* `recipient` (string): Destination address
* `amount` (Amount): Amount to transfer

#### Returns

`Call`: A StarkNet Call object

#### Throws

* If `amount.decimals` doesn't match the token's decimals
* If `amount.symbol` doesn't match the token's symbol (when set)

## Example

### Full Flow: Check Balance, Approve, Transfer

```typescript theme={null}
import { Erc20, Amount, TxBuilder, TokenRegistry } from "@chipi-stack/core";

const registry = new TokenRegistry("mainnet");
const usdcInfo = registry.bySymbol("USDC")!;
const usdc = new Erc20(usdcInfo, account);

const sendAmount = Amount.parse("25.0", usdcInfo);

// Check balance
const balance = await usdc.balanceOf(myAddress);
if (balance.lt(sendAmount)) {
  throw new Error(`Insufficient: ${balance.toFormatted()} < ${sendAmount.toFormatted()}`);
}

// Check allowance
const allowed = await usdc.allowance(myAddress, dexAddress);

// Build atomic transaction
const builder = new TxBuilder(account);
if (allowed.lt(sendAmount)) {
  builder.add(usdc.approveCall(dexAddress, sendAmount));
}
builder.add(usdc.transferCall(recipientAddress, sendAmount));

// Preview fee, then send
const fee = await builder.estimateFee();
console.log(`Fee: ${fee.overall_fee} wei`);

const result = await new TxBuilder(account)
  .add(usdc.approveCall(dexAddress, sendAmount))
  .add(usdc.transferCall(recipientAddress, sendAmount))
  .send();
```

## Related

* [Amount](/sdk/core/amount): The value type returned by `balanceOf()` and `allowance()`
* [TxBuilder](/sdk/core/tx-builder): Execute Call objects in atomic batches
* [TokenRegistry](/sdk/core/token-registry): Look up TokenInfo for the Erc20 constructor
