> For the complete documentation index, see [llms.txt](https://hinkal-team.gitbook.io/hinkal/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hinkal-team.gitbook.io/hinkal/hinkal-mobile-sdk/android/guides/withdrawals.md).

# Withdrawals

A withdrawal moves tokens from the private balance to a public address (`private → public`). It runs server-side through a Hinkal relayer, so no on-chain signature is needed from the user.

### Basic Withdrawal

```kotlin
val wei = Mobile.amountToWei(chainId, tokenAddress, "0.25")
val txHash = hinkal.withdraw(
    chainId,
    "[\"$tokenAddress\"]",
    "[\"$wei\"]",
    recipientPublicAddress,
    false,          // relayerOff
    tokenAddress,   // feeToken
    "",             // feeStructureJSON
)
```

### Parameters

<table data-search="false"><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>chainID</code></td><td><code>Long</code></td><td>Target chain id.</td></tr><tr><td><code>tokenAddrsJSON</code></td><td><code>String</code></td><td>JSON array of token addresses.</td></tr><tr><td><code>amountsWeiJSON</code></td><td><code>String</code></td><td>JSON array of amounts in wei.</td></tr><tr><td><code>recipient</code></td><td><code>String</code></td><td>Public address that receives the funds.</td></tr><tr><td><code>relayerOff</code></td><td><code>Boolean</code></td><td>Bypass the relayer and broadcast yourself.</td></tr><tr><td><code>feeToken</code></td><td><code>String</code></td><td>Token the relayer fee is paid in.</td></tr><tr><td><code>feeStructureJSON</code></td><td><code>String</code></td><td>Fee quote, or empty for defaults.</td></tr></tbody></table>

### Fees

The relayer fee is charged on top of the amount, so the private balance must cover `amount + fee`. Leave `feeStructureJSON` empty for defaults, or pass a quote obtained from the fee helpers on `Client` (`calculateTotalFee`, `getFeeStructureJSON`).

### Error Handling

```kotlin
try {
    val txHash = hinkal.withdraw(chainId, "[\"$tokenAddress\"]", "[\"$wei\"]",
                                 recipientPublicAddress, false, tokenAddress, "")
} catch (e: Exception) {
    Log.e("Hinkal", "Withdraw failed: ${e.message}")
}
```

### Best Practices

#### 1. Validate the amount and balance

Convert with `Mobile.amountToWei` (it throws on too many decimals) and confirm the private balance covers `amount + fee`.

```kotlin
val wei = Mobile.amountToWei(chainId, tokenAddress, amountText)
```

#### 2. Validate the recipient

Ensure `recipient` is a public address for the target chain.

#### 3. Handle long operations

Withdrawals run server-side and can take time. Show a loading indicator and refresh the balance afterward.

```kotlin
val txHash = hinkal.withdraw(chainId, "[\"$tokenAddress\"]", "[\"$wei\"]",
    recipient, false, tokenAddress, "")
hinkal.getTotalBalance(chainId, signature, address, true, false)
```
