Skip to content

Login with an external wallet

Authenticating a user with their Ethereum wallet is a three step process:

Privy allows you to authenticate a user via an Ethereum wallet using Sign in with Ethereum, or SIWE. This is a three step process:

  1. Generate a Sign-In With Ethereum (SIWE) message
  2. From a connected wallet, request an EIP-191 personal_sign signature for the SIWE message.
  3. Send the verified signature to Privy to authenticate the user's wallet

1. Generate a SIWE Message

To generate a SIWE message, call Privy's siwe.generateSiweMessage method. This returns the SIWE message for the user to sign as a String or throw an error.

An error could be thrown if the network call fails.

Method definition

swift
func generateSiweMessage(
    params: SiweMessageParams,
    metadata: WalletLoginMetadata?
) async throws -> String

SiweMessageParams - set of parameters required to generate the message.

FieldTypeDescription
appDomainStringYour app's domain. e.g. "my-domain.com"
appUriStringYour apps URI. e.g. "https://my-domain.com"
chainIdStringEVM Chain ID, e.g. "1" for Ethereum Mainnet
walletAddressStringThe user's ERC-55 compliant wallet address.

WalletLoginMetadata - Optionally, you can pass additional metadata that will be stored with the linked wallet. You can also override these meatdata params when calling loginWithSiwe in step 3.

FieldTypeDescription
walletClientTypeWalletClientTypeAn enum specifying the type of wallet used to login. e.g. WalletClientType.metamask
connectorTypeStringA string identifying how wallet was connected. e.g. "wallet_connect"

Example integration

swift
do {
    let params = SiweMessageParams(
        appDomain: "my-domain.com",
        appUri: "https://my-domain.com",
        chainId: "1",
        walletAddress: "0x12345..."
    )

    let metadata = WalletLoginMetadata(
        walletClientType: WalletClientType.metamask,
        connectorType: "wallet_connect"
    )

    let siweMessage = try await privy.siwe.generateSiweMessage(params: params, metadata: metadata)
} catch let error {
    // An error can be thrown if the network call to generate the message fails,
    // or if invalid metadata was passed in.
}

2. Request an EIP191 signature on the message

Using the message returned by generateSiweMessage, request an EIP-191 personal_sign signature from the user's connected wallet. You should do this using the library your app uses to connect to external wallets (e.g. the MetaMask iOS SDK or WalletConnect). Once the user successfully signs the message, store the signature in a variable.

3. Verify the SIWE signature

Authenticate the user by passing the user's signature as a String to Privy's loginWithSiwe method. Optionally, you can specify additional metadata about the user's wallet as a second optional WalletLoginMetadata parameter. If omitted, the metadata passed from generateSiweMessage will be used. If specified, metadata passed in generateSiweMessage will be overridden.

Method Definition

swift
func loginWithSiwe(
    _ signature: String,
    metadata: WalletLoginMetadata?
) async throws -> AuthState

Example integration

swift
do {
    // Pass signature to privy to authenticate user.
    // Omitting metadata because we specified it in step 1.
    let authState = try await privy.siwe.loginWithSiwe(signature)
} catch let error {
    // An error can be thrown if a successful call to `generateSiweMessage`
    // wasn't made prior to call `loginWithSiwe`
}

Tracking SIWE login flow state

You can add provide a listener to receive state updates during the login with SIWE process.

swift
privy.siwe.setSiweFlowStateChangeCallback{ siweFlowState in
    switch siweFlowState {
        case .initial:
            // Starting state
        case .generatingMessage:
            // SIWE message being created
        case .awaitingSignature:
            // Waiting for you to pass the signature generated from the personal_sign request
        case .submittingSignature:
            // Submitted signature to authenticate
        case .done:
            // Complete
        case .error:
            // An error has occurred
    }
}

That's it! Your user is now authenticated via external wallet.