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

# Get wallet addresses

> Read the client's wallet addresses for each supported chain with the Portal Android SDK.

After a client has a wallet, you can read its address for each supported chain. Addresses come from the client's wallet metadata in the Portal API, not from the signing shares on the device. An address tells you the client has a wallet, not that it can sign on this device. Use [`isWalletOnDeviceOrThrow`](./manage-wallet-lifecycle-states) to check that.

<Note>
  `getAddresses()` and the XRP Ledger, Stellar, and Tron addresses are available starting from SDK version 10.1.0.
</Note>

## Get every address

`getAddresses()` returns the client's addresses keyed by `PortalNamespace`.

```kotlin theme={null}
suspend fun getAddresses(): Map<PortalNamespace, String>
```

Which entries are present depends on the client's wallets:

| Key | Address | Present when the client has |
| - | - | - |
| `PortalNamespace.EIP155` | EVM address | a SECP256K1 wallet |
| `PortalNamespace.TRON` | Tron address | a SECP256K1 wallet |
| `PortalNamespace.XRPL` | XRP Ledger classic address | a SECP256K1 wallet |
| `PortalNamespace.SOLANA` | Solana address | an ED25519 wallet |
| `PortalNamespace.STELLAR` | Stellar address | an ED25519 wallet |

A namespace the client has no address for is left out of the map, so don't assume any entry is present, including `EIP155`. `PortalNamespace.BIP122` is never present; see [Get the Bitcoin address](#get-the-bitcoin-address).

`getAddresses()` throws an `IllegalStateException` if the client isn't set.

```kotlin theme={null}
import android.util.Log
import io.portalhq.android.storage.mobile.PortalNamespace

lifecycleScope.launch {
    try {
        val addresses = portal.getAddresses()

        addresses[PortalNamespace.EIP155]?.let { Log.d("[PortalEx]", "EVM address: $it") }
        addresses[PortalNamespace.XRPL]?.let { Log.d("[PortalEx]", "XRP Ledger address: $it") }

        addresses.forEach { (namespace, address) ->
            Log.d("[PortalEx]", "${namespace.value}: $address")
        }
    } catch (e: Exception) {
        Log.e("[PortalEx]", "Error reading addresses: ${e.message}")
    }
}
```

## Get one address

`getAddress` returns the address for a single chain ID or `PortalNamespace`, or `null` when the client has no address for that namespace.

```kotlin theme={null}
suspend fun getAddress(chainId: String): String?
suspend fun getAddress(chain: PortalNamespace): String?
```

The namespace part of a [CAIP-2 chain ID](../../../resources/chain-id-formatting) selects the address:

| Chain | Example chain IDs | `PortalNamespace` |
| - | - | - |
| EVM | `eip155:1`, `eip155:11155111` | `EIP155` |
| Solana | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | `SOLANA` |
| Stellar | `stellar:pubnet`, `stellar:testnet` | `STELLAR` |
| Tron | `tron:mainnet`, `tron:nile` | `TRON` |
| XRP Ledger | `xrpl:0`, `xrpl:1` | `XRPL` |

`getAddress` returns `null` for a `bip122:` chain ID. It throws an `IllegalArgumentException` for a malformed chain ID or an unsupported namespace, and an `IllegalStateException` if the client isn't set.

```kotlin theme={null}
import android.util.Log
import io.portalhq.android.storage.mobile.PortalNamespace

lifecycleScope.launch {
    try {
        val xrplAddress = portal.getAddress("xrpl:0")
        val stellarAddress = portal.getAddress(PortalNamespace.STELLAR)

        Log.d("[PortalEx]", "XRP Ledger address: ${xrplAddress ?: "none"}")
        Log.d("[PortalEx]", "Stellar address: ${stellarAddress ?: "none"}")
    } catch (e: Exception) {
        Log.e("[PortalEx]", "Error reading the address: ${e.message}")
    }
}
```

## Get the Bitcoin address

Bitcoin has a separate address per network, so it isn't in the `getAddresses()` map. Read the P2WPKH addresses from the client details:

```kotlin theme={null}
import android.util.Log

lifecycleScope.launch {
    try {
        val p2wpkh = portal.api.getClient().metadata.namespaces.bip122?.bitcoin?.p2wpkh

        Log.d("[PortalEx]", "Bitcoin mainnet address: ${p2wpkh?.mainnet}")
        Log.d("[PortalEx]", "Bitcoin testnet address: ${p2wpkh?.testnet}")
    } catch (e: Exception) {
        Log.e("[PortalEx]", "Error reading the client: ${e.message}")
    }
}
```

## PortalNamespace

```kotlin theme={null}
enum class PortalNamespace(val value: String) {
    EIP155("eip155"),
    SOLANA("solana"),
    BIP122("bip122"),
    STELLAR("stellar"),
    TRON("tron"),
    XRPL("xrpl"),
}
```

`STELLAR`, `TRON`, and `XRPL` are new in 10.1.0. If you use an exhaustive `when` over `PortalNamespace`, add branches for them.

## Notes

* The XRP Ledger, Stellar, and Tron addresses are derived from the client's existing wallets. No new wallet is created.
* Signing with an XRP Ledger, Stellar, or Tron chain ID isn't supported yet. `portal.request(...)` and `portal.rawSign(...)` called with one of these chain IDs throw `PortalException.Blockchain.NoSupportedCurveForChainId`, and `portal.sendAsset(...)` returns a failed `Result` with `PortalException.Transaction.SendAssetArgumentError`. [Raw sign](./sign-a-transaction#raw-sign) selects the key by an `eip155` (SECP256K1) or `solana` (ED25519) chain ID.
* Starting from SDK version 10.1.0, a namespace without an address is left out of the address map instead of being mapped to an empty string, so `getAddress` returns `null` for it.
* The wallet-status methods also accept these chain IDs and namespaces. See [Manage wallet lifecycle states](./manage-wallet-lifecycle-states).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.