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

# setSignAndSendTransaction

> Sets the instance-level signer used by the high-level delegation submit methods to sign and broadcast each delegation transaction.

**Function Signature**

```swift theme={null}
public func setSignAndSendTransaction(
    _ fn: @escaping DelegationSignAndSend
)
```

Where:

```swift theme={null}
public typealias DelegationSignAndSend = (
    _ transaction: DelegationTransaction,
    _ chainId: String
) async throws -> String
```

**Description**

Replaces the signer that `approveAndSubmit`, `revokeAndSubmit`, and `transferAndSubmit` use when no per-call `DelegationSubmitOptions.signAndSendTransaction` is provided. The signer receives one transaction and the CAIP-2 chain ID, signs and broadcasts it, and returns the transaction hash.

`Portal` already installs a signer on `portal.delegations` that routes `.evm` transactions to `eth_sendTransaction` and `.solana` transactions to `sol_signAndSendTransaction`, so you only need this method to change that behavior — for example to attach a `signatureApprovalMemo`, add your own logging, or route signing through a different key.

Signer precedence is **per-call `DelegationSubmitOptions.signAndSendTransaction` → the signer set here → the `Portal` default**.

**Parameters**

| Parameter | Type                    | Required | Description                                                                                                                                                                      |
| --------- | ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fn`      | `DelegationSignAndSend` | Yes      | Signs and broadcasts a single `DelegationTransaction` and returns its hash. Returning an empty hash causes the submit method to throw `DelegationsError.invalidTransactionHash`. |

The `transaction` argument is a `DelegationTransaction`:

```swift theme={null}
public enum DelegationTransaction: Equatable {
    case evm(ConstructedEipTransaction)
    case solana(String) // base64-encoded

    public var evmTransaction: ConstructedEipTransaction? { get }
    public var solanaTransaction: String? { get }
}
```

Each accessor returns `nil` for the other case, so you can branch with `if let` instead of writing a full `switch`. `ConstructedEipTransaction` is `Codable`, so you can encode it for logging or to hand it off to another process.

| Field   | Type      | Description                        |
| ------- | --------- | ---------------------------------- |
| `from`  | `String`  | The sender address.                |
| `to`    | `String`  | The contract or recipient address. |
| `data`  | `String?` | The calldata, when present.        |
| `value` | `String?` | The native value, when present.    |

**Returns**

Nothing. The signer is stored on the instance and used by subsequent submit calls.

**Throws**

Nothing. Errors from the signer itself surface from whichever submit method invoked it.

**Notes**

* The stored signer is not access-synchronized. Set it once — during app setup, before any submit call — rather than changing it while a submit is in flight. To vary the signer per call, pass `DelegationSubmitOptions.signAndSendTransaction` instead.

**Example Usage**

```swift theme={null}
import PortalSwift

enum MyAppError: Error {
    case missingTransactionHash
    case unsupportedTransaction
}

func sendEvmDelegationTransaction(
    _ transaction: ConstructedEipTransaction,
    chainId: String
) async throws -> String {
    var params: [String: String] = [
        "from": transaction.from,
        "to": transaction.to
    ]
    if let data = transaction.data { params["data"] = data }
    if let value = transaction.value { params["value"] = value }

    let response = try await portal.request(
        chainId: chainId,
        method: .eth_sendTransaction,
        params: [params],
        options: RequestOptions(signatureApprovalMemo: "Delegation transaction")
    )
    guard let hash = response.result as? String else {
        throw MyAppError.missingTransactionHash
    }
    return hash
}

func sendSolanaDelegationTransaction(
    _ encodedTransaction: String,
    chainId: String
) async throws -> String {
    let response = try await portal.request(
        chainId: chainId,
        method: .sol_signAndSendTransaction,
        params: [encodedTransaction],
        options: RequestOptions(signatureApprovalMemo: "Delegation transaction")
    )
    guard let hash = response.result as? String else {
        throw MyAppError.missingTransactionHash
    }
    return hash
}

// Branch with the accessors
portal.delegations.setSignAndSendTransaction { transaction, chainId in
    if let evmTransaction = transaction.evmTransaction {
        return try await sendEvmDelegationTransaction(evmTransaction, chainId: chainId)
    }
    if let encodedTransaction = transaction.solanaTransaction {
        return try await sendSolanaDelegationTransaction(encodedTransaction, chainId: chainId)
    }
    throw MyAppError.unsupportedTransaction
}

// Or match the enum, when you want the compiler to make you handle both cases
portal.delegations.setSignAndSendTransaction { transaction, chainId in
    switch transaction {
    case let .evm(evmTransaction):
        return try await sendEvmDelegationTransaction(evmTransaction, chainId: chainId)
    case let .solana(encodedTransaction):
        return try await sendSolanaDelegationTransaction(encodedTransaction, chainId: chainId)
    }
}

// Every submit call now goes through your signer
Task {
    do {
        let request = ApproveDelegationRequest(
            chain: "eip155:11155111",
            token: "USDC",
            delegateAddress: "0xa944e86eb36f039becd1843132347eb5b8501562",
            amount: "0.01"
        )

        let result = try await portal.delegations.approveAndSubmit(request: request)

        print("Submitted hashes: \(result.hashes)")
    } catch DelegationsError.invalidTransactionHash(let index, let chainId) {
        print("Signer returned an unusable hash for transaction \(index) on \(chainId)")
    } catch {
        print("Error approving and submitting delegation: \(error)")
    }
}
```

**Related Documentation**

* [Manage Token Delegations](../guide/delegations)
* [Token delegations](/resources/delegations)
