Appearance
Signatures
Ethereum
Privy supports requesting both EIP191 personal_sign
and EIP712 eth_signTypedData_v4
signatures from a user's embedded wallet.
Signing messages (EIP191)
To request an EIP191 signature from a user's embedded wallet, send a personal_sign
JSON-RPC request to the wallet's EIP1193 provider.
As a parameter to request
, pass an object with the fields:
method
:'personal_sign'
params
:[<insert-message>, <insert-wallet-address>]
swift
func personalSign() async throws {
guard case .connected(let wallets) = privy.embeddedWallet.embeddedWalletState else {
print("Wallet not connected")
return
}
guard let wallet = wallets.first, wallet.chainType == .ethereum else {
print("No Ethereum wallets available")
return
}
// Get the provider for wallet
let provider = try privy.embeddedWallet.getEthereumProvider(for: wallet.address)
let signature = try await provider.request(
RpcRequest(
method: "personal_sign",
params: ["This is the message that is being signed", wallet.address]
)
)
print(signature)
}
Signing typed data (EIP712)
To request an EIP712 signature from a user's embedded wallet, send an eth_signTypedData_v4
JSON-RPC request to the wallet's EIP1193 provider.
As a parameter to request
, pass an object with the fields:
method
:'eth_signTypedData_v4'
params
:[<insert-wallet-address>, <insert-stringified-typed-data>]
swift
// Define a struct to represent your typed data
struct Param: Codable {
let types: ParamTypes
let primaryType: String
let domain: Domain
let message: Message
}
struct ParamTypes: Codable {
let eIP712Domain: [DomainType]
let person: [DomainType]
let mail: [DomainType]
enum CodingKeys: String, CodingKey {
case eIP712Domain = "EIP712Domain"
case person = "Person"
case mail = "Mail"
}
}
struct DomainType: Codable {
let name: String
let type: String
}
struct Domain: Codable {
let name: String
let version: String
let chainId: Int
let verifyingContract: String
}
struct Message: Codable {
struct W: Codable {
let name: String
let wallet: String
}
let from: W
let to: W
let contents: String
}
func typedData() async throws {
guard case .connected(let wallets) = privy.embeddedWallet.embeddedWalletState else {
print("Wallet not connected")
return
}
guard let wallet = wallets.first, wallet.chainType == .ethereum else {
print("No Ethereum wallets available")
return
}
// Get RPC provider for wallet
let provider = try privy.embeddedWallet.getEthereumProvider(for: wallet.address)
let typedData = Param(
types: ParamTypes(
eIP712Domain: [
DomainType(name: "name", type: "string"),
DomainType(name: "version", type: "string"),
DomainType(name: "chainId", type: "uint256"),
DomainType(name: "verifyingContract", type: "address"),
],
person: [
DomainType(name: "name", type: "string"),
DomainType(name: "wallet", type: "address")
],
mail: [
DomainType(name: "from", type: "Person"),
DomainType(name: "to", type: "Person"),
DomainType(name: "contents", type: "string"),
]
), primaryType: "Mail",
domain: Domain(
name: "Ether Mail",
version: "1",
chainId: 1,
verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
),
message: Message(
from: Message.W(name: "Cow", wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"),
to: Message.W(name: "Bob", wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"),
contents: "Hello, Bob!"
)
)
let encodedTypedData = try JSONEncoder().encode(typedData)
guard let typedDataStr = String(data: encodedTypedData, encoding: .utf8) else {
print("Data parse error")
return
}
let signature = try await provider.request(
RpcRequest(
method: "eth_signTypedData_v4",
params: [wallet.address, typedDataStr]
)
)
print(signature)
}