> ## Documentation Index
> Fetch the complete documentation index at: https://rain-sandbox-trial.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Balances & Transactions

> Reference for the Balance and WalletTransaction types, send methods, and error codes the embedded wallet SDK exposes.

Query native and token balances, fetch transaction history, and send tokens directly from your app once you've [set up a wallet](/sdks/embedded-wallets-setup). Every method here runs against the resolved `RainClient`.

## Query a balance

Get a single balance: native or a specific token. Pass `.native` for the chain's native token, or `.contract(address:)` for an ERC-20. The SDK resolves the token's decimals and symbol for you.

<CodeGroup>
  ```swift iOS theme={null}
  let avax = try await client.getBalance(chainId: RainChain.avalancheMainnet, token: .native)

  let usdc = try await client.getBalance(
      chainId: RainChain.avalancheMainnet,
      token: .contract(address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E")
  )
  print(usdc.formatted)  // "1.5"
  print(usdc.rawAmount)  // exact base units, for example 1500000
  ```

  ```kotlin Android theme={null}
  import com.rain.sdk.RainChain
  import com.rain.sdk.models.Token

  val avax = client.getBalance(chainId = RainChain.AVALANCHE_MAINNET, token = Token.Native)

  val usdc = client.getBalance(
      chainId = RainChain.AVALANCHE_MAINNET,
      token = Token.contract("0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E")
  )
  println("${usdc.formatted} ${usdc.symbol}")  // "1.5 USDC"
  ```
</CodeGroup>

## Query every balance on a chain

Get all non-zero balances for the wallet on one network. The native balance is always included.

<CodeGroup>
  ```swift iOS theme={null}
  let balances: [Balance] = try await client.getTokenBalances(chainId: RainChain.avalancheMainnet)
  ```

  ```kotlin Android theme={null}
  val balances: List<Balance> = client.getTokenBalances(chainId = RainChain.AVALANCHE_MAINNET)
  ```
</CodeGroup>

## Query balances across all chains

Get balances across every configured chain in one call, flattened into a single list. Each `Balance` carries its own `chainId`, and a chain that fails contributes no entries rather than failing the whole call.

<CodeGroup>
  ```swift iOS theme={null}
  let all: [Balance] = try await client.getAllBalances()
  ```

  ```kotlin Android theme={null}
  val all: List<Balance> = client.getAllBalances()
  ```
</CodeGroup>

### The Balance type

Every balance method returns a rich `Balance`: the exact base-unit amount, never a lossy `Double`.

| Field           | Type                     | Description                                   |
| --------------- | ------------------------ | --------------------------------------------- |
| `token`         | `Token`                  | `.native` or `.contract(address:)`            |
| `chainId`       | `Int`                    | Chain the balance was read on                 |
| `rawAmount`     | `BigUInt` / `BigInteger` | Exact balance in the token's smallest unit    |
| `decimals`      | `Int`                    | Token decimal places (6 for USDC, 18 for ETH) |
| `symbol`        | `String?`                | Token symbol, when known                      |
| `name`          | `String?`                | Human-readable name, when known               |
| `decimalAmount` | `Decimal` / `BigDecimal` | Derived `rawAmount / 10^decimals`             |
| `formatted`     | `String`                 | Derived display string (for example `"1.5"`)  |

Metadata for well-known tokens is built in; unknown tokens are resolved on-chain once and cached. To resolve a token without any on-chain lookup, register it up front with `registerTokens(...)` on the builder, the SDK, or the client.

## Send native tokens

Send the chain's native token (for example AVAX). Both platforms return a `RainTokenTransferResult` carrying the `transactionHash`.

<CodeGroup>
  ```swift iOS theme={null}
  let result = try await client.sendNative(
      chainId: RainChain.avalancheMainnet,
      to: "0x3cA8ac240F6ebeA8684b3E629A8e8C1f0E3bC0Ff",
      amount: 0.1
  )
  print(result.transactionHash)
  ```

  ```kotlin Android theme={null}
  import java.math.BigDecimal

  val result = client.sendNativeToken(
      chainId = RainChain.AVALANCHE_MAINNET,
      toAddress = "0x3cA8ac240F6ebeA8684b3E629A8e8C1f0E3bC0Ff",
      amount = BigDecimal("0.1")
  )
  println(result.transactionHash)
  ```
</CodeGroup>

## Send tokens

Send an ERC-20 token. Omit `decimals` to let the SDK resolve them.

<CodeGroup>
  ```swift iOS theme={null}
  let result = try await client.sendToken(
      chainId: RainChain.avalancheMainnet,
      contractAddress: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
      to: "0x3cA8ac240F6ebeA8684b3E629A8e8C1f0E3bC0Ff",
      amount: 100
  )
  print(result.transactionHash)
  ```

  ```kotlin Android theme={null}
  val result = client.sendToken(
      chainId = RainChain.AVALANCHE_MAINNET,
      contractAddress = "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
      toAddress = "0x3cA8ac240F6ebeA8684b3E629A8e8C1f0E3bC0Ff",
      amount = BigDecimal("100.0")
  )
  println(result.transactionHash)
  ```
</CodeGroup>

Amounts are converted to base units exactly. On iOS, `RainTokenTransferResult.transactionHash` carries the EVM hash, or the Solana signature for Solana-routed sends (sentinel chain ids `101`/`102`/`103`, provider support required).

<Note>
  Sends through the **Portal** and **Privy** adapters are simulated with `eth_call` before broadcasting: a transfer that would revert throws [`RAIN_403`](/sdks/embedded-wallets-error-reference) before any gas is spent. **Turnkey** sends are not simulated and go straight to broadcast.
</Note>

## Fetch transaction history

Retrieve the wallet's transaction history with optional pagination and sort order.

<CodeGroup>
  ```swift iOS theme={null}
  let transactions: [WalletTransaction] = try await client.getTransactions(
      chainId: RainChain.avalancheMainnet,
      limit: 20,
      offset: 0,
      order: .DESC
  )
  for tx in transactions {
      print("\(tx.hash) — \(tx.value ?? 0) \(tx.asset ?? "")")
  }
  ```

  ```kotlin Android theme={null}
  import com.rain.sdk.models.RainTransactionOrder

  val result = client.getTransactions(
      chainId = RainChain.AVALANCHE_MAINNET,
      limit = 20,
      offset = 0,
      order = RainTransactionOrder.DESC
  )
  for (tx in result.transactions) {
      println("${tx.hash} — ${tx.value} ${tx.symbol}")
  }
  ```
</CodeGroup>

On iOS, `getTransactions` returns `[WalletTransaction]` directly. On Android, it returns a `RainTransactionResult` with a `transactions` list. The **Privy** adapter returns an empty result, since Privy has no history endpoint.

Here's what each field carries:

<Tabs>
  <Tab title="Android: RainTransaction">
    | Field            | Type                 | Description                                          |
    | ---------------- | -------------------- | ---------------------------------------------------- |
    | `hash`           | `String`             | Transaction hash (`0x...`)                           |
    | `from`           | `String`             | Sender address                                       |
    | `to`             | `String?`            | Recipient address                                    |
    | `value`          | `String?`            | Native token amount transferred                      |
    | `blockNumber`    | `String?`            | Block height as a decimal string                     |
    | `blockTimestamp` | `String?`            | ISO-8601 timestamp of the block                      |
    | `gas`            | `String?`            | Gas used by the transaction                          |
    | `gasPrice`       | `String?`            | Gas price paid                                       |
    | `chainId`        | `String?`            | CAIP-2 chain identifier (for example `eip155:43114`) |
    | `symbol`         | `String?`            | Token symbol (for example `AVAX`, `USDC`)            |
    | `tokenAddress`   | `String?`            | ERC-20 contract address (null for native)            |
    | `metadata`       | `Map<String, Any?>?` | Additional provider-supplied metadata                |
  </Tab>

  <Tab title="iOS: WalletTransaction">
    | Field                       | Type           | Description                                         |
    | --------------------------- | -------------- | --------------------------------------------------- |
    | `hash`                      | `String`       | Transaction hash (`0x...`)                          |
    | `from`                      | `String`       | Sender address                                      |
    | `to`                        | `String?`      | Recipient address                                   |
    | `value`                     | `Double?`      | Native token amount                                 |
    | `asset`                     | `String?`      | Token symbol (for example `AVAX`, `USDC`)           |
    | `category`                  | `String`       | Transfer category (for example `external`, `erc20`) |
    | `blockNum`                  | `String`       | Block height (provider-supplied format)             |
    | `uniqueId`                  | `String`       | Provider-supplied unique identifier                 |
    | `tokenId` / `erc721TokenId` | `String?`      | NFT token ids, when applicable                      |
    | `erc1155Metadata`           | `[...]?`       | ERC-1155 transfer metadata                          |
    | `rawContract`               | `RawContract?` | Raw contract value/decimals                         |
    | `metadata`                  | `Metadata?`    | Wraps `blockTimestamp`                              |
    | `chainId`                   | `Int`          | Numeric chain ID (for example `43114`)              |
  </Tab>
</Tabs>

Field availability depends on what the underlying RPC provider returns. Treat optional fields as actually optional and code defensively.

## Deprecated shims (Android)

The pre-modular `Double`-based methods survive as `@Deprecated` default implementations so existing integrations keep compiling:

* `getAddress()`
* `getNativeBalance`
* `getERC20Balance`
* `getERC20Balances`
* `getBalances` (map form)
* `sendToken(amount: Double, decimals: Int)`

Migrate to the `Balance`/`BigDecimal` API: the shims lose precision by design.

## Error handling

Balance and transaction methods can throw:

| Code      | Meaning                                           |
| --------- | ------------------------------------------------- |
| RAIN\_101 | SDK not built, or no wallet provider resolved     |
| RAIN\_301 | Network error reaching the RPC endpoint           |
| RAIN\_402 | Insufficient funds for the transfer or gas        |
| RAIN\_403 | Preflight simulation reverted before submission   |
| RAIN\_404 | Wallet unavailable (no address from the provider) |
| RAIN\_501 | Provider error                                    |

See the full [Error Reference](/sdks/embedded-wallets-error-reference) for all codes and handling patterns.

## What's next

<Columns cols={3}>
  <Card title="Sends & DeFi" icon="arrows-rotate" href="/sdks/embedded-wallets-defi">
    Make arbitrary sends and contract calls.
  </Card>

  <Card title="Withdraw Collateral" icon="arrow-right-from-bracket" href="/sdks/embedded-wallets-withdraw-collateral">
    Execute collateral withdrawals from your app.
  </Card>

  <Card title="Error Reference" icon="circle-exclamation" href="/sdks/embedded-wallets-error-reference">
    Handle SDK errors with standardized error codes.
  </Card>
</Columns>
