> 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/ios/guides/wallet-integration.md).

# Wallet Integration

The SDK never holds a private key. Your app implements a host signer interface for its wallet type, and the SDK calls it to read the address and request signatures.

### MobileHostWalletProtocol (EVM)

The Swift protocol is `MobileHostWalletProtocol`. Its methods use an `error: NSErrorPointer` out-parameter (set it on failure); only `switchChain` is `throws`.

```swift
class WalletHost: NSObject, MobileHostWalletProtocol {
    let wallet: YourWalletImplementation

    func address(_ error: NSErrorPointer) -> String { wallet.address }
    func chainID() -> Int64 { wallet.chainId }
    func personalSign(_ message: String?, error: NSErrorPointer) -> String {
        wallet.personalSign(message ?? "")
    }
    func sendTransaction(_ toHex: String?, dataHex: String?, valueDec: String?,
                         gasLimit: Int64, error: NSErrorPointer) -> String {
        wallet.sendTransaction(toHex ?? "", dataHex ?? "", valueDec ?? "", gasLimit)
    }
    func switchChain(_ chainID: Int64) throws { try wallet.switchChain(chainID) }
}
```

| Method            | Purpose                                                |
| ----------------- | ------------------------------------------------------ |
| `address`         | The wallet's public address.                           |
| `chainID`         | The wallet's current chain id.                         |
| `personalSign`    | EIP-191 personal\_sign of a message.                   |
| `sendTransaction` | Sign and broadcast a transaction; returns the tx hash. |
| `switchChain`     | Switch the wallet to another chain.                    |

### MobileHostSolanaSignerProtocol

`publicKey` uses the `error:` out-parameter; the signing methods are `throws` and return non-optional `Data`.

```swift
class SolanaHost: NSObject, MobileHostSolanaSignerProtocol {
    func publicKey(_ error: NSErrorPointer) -> String { wallet.publicKey }
    func signMessage(_ message: Data?) throws -> Data { try wallet.signMessage(message ?? Data()) }
    func signTransaction(_ tx: Data?) throws -> Data { try wallet.signTransaction(tx ?? Data()) }
}
```

### MobileHostTronSignerProtocol

```swift
class TronHost: NSObject, MobileHostTronSignerProtocol {
    func address(_ error: NSErrorPointer) -> String { wallet.address }
    func signMessage(_ message: String?) throws -> Data { try wallet.signMessage(message ?? "") }
    func signTxHash(_ txHash: Data?) throws -> Data { try wallet.signTxHash(txHash ?? Data()) }
}
```

### Connecting

```swift
try call { client.connect(WalletHost(wallet: yourWallet), error: &$0) }              // EVM
try call { client.connectSolana(SolanaHost(), chainID: solanaChainId, error: &$0) }  // Solana
try call { client.connectTron(TronHost(), chainID: tronChainId, error: &$0) }        // Tron
```

### Best Practices

#### 1. Never let the key reach the SDK

The host only returns an address and signatures. Keep the private key in your wallet/keychain; the SDK never asks for it.

#### 2. Set the error pointer on failure

If signing fails, set the `error` out-parameter so the SDK surfaces the failure instead of treating an empty string as success.

```swift
func personalSign(_ message: String?, error: NSErrorPointer) -> String {
    do { return try wallet.personalSign(message ?? "") }
    catch { error?.pointee = error as NSError; return "" }
}
```

#### 3. Match the host to the chain

Implement `MobileHostWalletProtocol` for EVM, `MobileHostSolanaSignerProtocol` for Solana, `MobileHostTronSignerProtocol` for Tron, and connect with the matching method.
