> ## 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.

# generateIdempotencyKey

> Generates a lowercased UUID v4 for use as an idempotency key on a transaction send.

**Function Signature**

```swift theme={null}
public func generateIdempotencyKey() -> String
```

**Description**

Generates an idempotency key for a transaction send. This is a free function on the `PortalSwift` module. It is not a method on `Portal`, so no wallet or client is required to call it.

The returned value is a lowercased UUID v4, which always meets Portal's key rules (1–255 characters of `A-Z a-z 0-9 . _ ~ -`).

Pass the result to `RequestOptions(idempotencyKey:)` for `eth_sendTransaction`, `sol_signAndSendTransaction` or `sol_signAndConfirmTransaction`, or to `SendAssetParams(idempotencyKey:)` for `sendAsset` on EVM and Solana chains. Portal broadcasts a key at most once while it remembers the key (at least 24 hours after the request was last updated), so a retry with the same key within that time cannot send the same transaction twice.

**Parameters**

* None.

**Returns**

* `String`: a lowercased UUID v4, for example `"550e8400-e29b-41d4-a716-446655440000"`.

**Throws**

* Nothing. This function cannot fail.

**Related Types**

```swift theme={null}
public enum PortalIdempotencyErrorId {
  public static let requestInProgress = "IDEMPOTENT_REQUEST_IN_PROGRESS"
  public static let requestAlreadyCompleted = "IDEMPOTENT_REQUEST_ALREADY_COMPLETED"
  public static let requestPreviouslyFailed = "IDEMPOTENT_REQUEST_PREVIOUSLY_FAILED"
  public static let requestUnexpectedState = "IDEMPOTENT_REQUEST_UNEXPECTED_STATE"
  public static let keyReused = "IDEMPOTENCY_KEY_REUSED"
  public static let txMissing = "IDEMPOTENT_TX_MISSING"

  public static let all: Set<String>
}

public enum PortalIdempotencyError: LocalizedError, Equatable {
  case invalidKey(String)
  case unsupportedTarget(String)
}
```

* `PortalIdempotencyErrorId` holds the error IDs Portal returns, as `PortalMpcError.id`, when it rejects a request because of its key. `PortalMpcError.isIdempotencyRejection` checks for any of them, and `PortalMpcError.isIdempotencyKeyReused` checks for `keyReused`.
* `PortalIdempotencyError` is thrown by the SDK before anything is signed or sent: `invalidKey` for a key that breaks the rules above, and `unsupportedTarget` for a key on `eth_sendRawTransaction`, `sol_sendTransaction` or a Bitcoin `sendAsset`. The associated value describes the problem and never contains the key.

**Example Usage**

```swift theme={null}
import PortalSwift

do {
    let portal = try Portal(
      "YOUR_CLIENT_API_KEY",
      withRpcConfig: ["eip155:11155111": "https://sepolia.infura.io/v3/YOUR_INFURA_KEY"]
    )

    // Generate one key per transfer and store it with the pending transfer,
    // so a retry can reuse it.
    let idempotencyKey = generateIdempotencyKey()

    let response = try await portal.sendAsset(
      chainId: "eip155:11155111",
      params: SendAssetParams(
        to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
        amount: "0.01",
        token: "NATIVE",
        idempotencyKey: idempotencyKey
      )
    )

    print("Submitted — txHash: \(response.txHash)")
} catch let error as PortalMpcError where error.isIdempotencyRejection {
    print("Portal already handled this key: \(error.id ?? "unknown")")
} catch {
    print("Failed: \(error)")
}
```

**Notes**

* Generate one key per operation, not per attempt. Reuse it only to retry the identical request.
* Portal remembers a key for at least 24 hours after the request was last updated, then removes it. Once the key is removed, the same key is treated as a new request, so check the chain before retrying an operation that is older than 24 hours.
* No rejection returns the original transaction hash. Check the chain before sending an operation again under a new key.

**Related Documentation**

* [Idempotency keys](../guide/idempotency-keys)
* [Send tokens](../guide/send-tokens)
* [Sign a transaction](../guide/sign-a-transaction)


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