Appearance
Login with an external wallet
Privy allows you to authenticate a user via an Ethereum wallet using Sign in with Ethereum, or SIWE. This is a three step process:
- Generate a Sign-In With Ethereum (SIWE) message
- From a connected wallet, request an EIP-191
personal_sign
signature for the SIWE message. - Send the verified signature to Privy to authenticate the user's wallet
TIP
With Privy, users can either login with their wallet or link their wallet to an existing account.
1. Generate a SIWE Message
To login a user by their Ethereum wallet or to have them link their wallet to an existing account, first generate a SIWE message for the user by calling 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.
Field | Type | Description |
---|---|---|
appDomain | String | Your app's domain. e.g. "my-domain.com" |
appUri | String | Your apps URI. e.g. "https://my-domain.com" |
chainId | String | EVM Chain ID, e.g. "1" for Ethereum Mainnet |
walletAddress | String | The 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.
Field | Type | Description |
---|---|---|
walletClientType | WalletClientType | An enum specifying the type of wallet used to login. e.g. WalletClientType.metamask |
connectorType | String | A 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. Authenticate the wallet
Once the user has signed the SIWE message, login the user via their wallet by passing the signature to the loginWithSiwe
method, or have them link their wallet to an existing account by passing the signature to the linkWithSiwe
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.