***

## description: Transfer TIP-20 tokens, authorize spenders, and read balances on Tempo.

# Transfer Tokens

## Overview

Any TIP-20 holder can transfer their balance to another account or approve a spender to move tokens
on their behalf. Reads like balances and allowances let you reflect token state in your application.

[See the TIP-20 specification](https://docs.tempo.xyz/protocol/tip20/overview)

## Recipes

These recipes assume you have [set up a Tempo client](/tempo).

### Transfer Tokens

Move tokens from your account to another with
[`token.transferSync`](/tempo/actions/token.transfer). Amounts are in the token's base units, so use
[`parseUnits`](/docs/utilities/parseUnits) with the token's decimals.

:::code-group

```ts twoslash [example.ts]
import { parseUnits } from 'viem'
import { client } from './viem.config'

const { receipt } = await client.token.transferSync({
  amount: parseUnits('10.5', 6),
  to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
  token: '0x20c0000000000000000000000000000000000000',
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
// [!include ~/snippets/tempo/viem.config.ts:setup]
```

:::

### Approve a Spender

Authorize another account to spend your tokens with
[`token.approveSync`](/tempo/actions/token.approve), then read the remaining allowance with
[`token.getAllowance`](/tempo/actions/token.getAllowance).

:::code-group

```ts twoslash [example.ts]
import { parseUnits } from 'viem'
import { client } from './viem.config'

const { receipt } = await client.token.approveSync({
  amount: parseUnits('10.5', 6),
  spender: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
  token: '0x20c0000000000000000000000000000000000000',
})

const allowance = await client.token.getAllowance({
  account: client.account.address,
  spender: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
  token: '0x20c0000000000000000000000000000000000000',
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
// [!include ~/snippets/tempo/viem.config.ts:setup]
```

:::

### Read a Balance

Read any account's balance with [`token.getBalance`](/tempo/actions/token.getBalance). The value is
returned in the token's base units.

:::code-group

```ts twoslash [example.ts]
import { client } from './viem.config'

const balance = await client.token.getBalance({
  account: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
  token: '0x20c0000000000000000000000000000000000000',
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
// [!include ~/snippets/tempo/viem.config.ts:setup]
```

:::

## Best Practices

### Always Use Base Units

Token amounts are integers in the token's smallest unit. Convert human-readable values with
[`parseUnits`](/docs/utilities/parseUnits) and format them back with
[`formatUnits`](/docs/utilities/formatUnits) using the token's decimals to avoid off-by-magnitude
errors.

### Prefer Direct Transfers Over Approve Plus Transfer

If you control both the sender and the flow, a single `token.transfer` is cheaper and simpler than an
approve followed by a third-party transfer. Reserve approvals for cases where another contract or
account must pull funds.

### Reset Allowances Deliberately

Setting a new allowance overwrites the previous one. When reducing a spender's allowance, set it to
the exact new value rather than assuming it adds to the existing amount.

## See More

<Cards>
  <Card icon="lucide:flame" title="Mint & Burn Tokens" description="Issue and destroy token supply as an issuer." to="/tempo/guides/manage-token-balances" />

  <Card icon="lucide:shield-check" title="Configure Transfer Policies" description="Gate which accounts may send or receive the token." to="/tempo/guides/transfer-policies" />

  <Card icon="lucide:square-function" title="token.transfer" description="Transfer TIP-20 tokens between accounts." to="/tempo/actions/token.transfer" />

  <Card icon="lucide:book-open" title="Tempo Docs: TIP-20" description="The TIP-20 stablecoin token standard." to="https://docs.tempo.xyz/protocol/tip20/overview" />
</Cards>
