UNPKG

near-safe

Version:

An SDK for controlling Ethereum Smart Accounts via ERC4337 from a Near Account.

84 lines (83 loc) 3.11 kB
import { gte } from "semver"; import { fromHex, hashMessage, hashTypedData, isHex, } from "viem"; /* * From v1.3.0, EIP-1271 support was moved to the CompatibilityFallbackHandler. * Also 1.3.0 introduces the chainId in the domain part of the SafeMessage */ const EIP1271_FALLBACK_HANDLER_SUPPORTED_SAFE_VERSION = "1.3.0"; const generateSafeMessageMessage = (message) => { return typeof message === "string" ? hashMessage(message) : hashTypedData(message); }; /** * Generates `SafeMessage` typed data for EIP-712 * https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol#L12 * @param safe Safe which will sign the message * @param message Message to sign * @returns `SafeMessage` types for signing */ const generateSafeMessageTypedData = ({ version, chainId, address }, message) => { if (!version) { throw Error("Cannot create SafeMessage without version information"); } const isHandledByFallbackHandler = gte(version, EIP1271_FALLBACK_HANDLER_SUPPORTED_SAFE_VERSION); const verifyingContract = address.value; return { domain: isHandledByFallbackHandler ? { chainId: Number(BigInt(chainId)), verifyingContract, } : { verifyingContract }, types: { SafeMessage: [{ name: "message", type: "bytes" }], }, message: { message: generateSafeMessageMessage(message), }, primaryType: "SafeMessage", }; }; const generateSafeMessageHash = (safe, message) => { const typedData = generateSafeMessageTypedData(safe, message); return hashTypedData(typedData); }; /** * If message is a hex value and is Utf8 encoded string we decode it, else we return the raw message * @param {string} message raw input message * @returns {string} */ const getDecodedMessage = (message) => { if (isHex(message)) { try { return fromHex(message, "string"); } catch (e) { // the hex string is not UTF8 encoding so return the raw message. } } return message; }; /** * Returns the decoded message, the hash of the `message` and the hash of the `safeMessage`. * The `safeMessageMessage` is the value inside the SafeMessage and the `safeMessageHash` gets signed if the connected wallet does not support `eth_signTypedData`. * * @param message message as string, UTF-8 encoded hex string or EIP-712 Typed Data * @param safe SafeInfo of the opened Safe * @returns `{ * decodedMessage, * safeMessageMessage, * safeMessageHash * }` */ export function decodeSafeMessage(message, safe) { const decodedMessage = typeof message === "string" ? getDecodedMessage(message) : message; return { decodedMessage, safeMessageMessage: generateSafeMessageMessage(decodedMessage), safeMessageHash: generateSafeMessageHash(safe, decodedMessage), }; } // export const isBlindSigningPayload = (obj: EIP712TypedData | string): boolean => // !isEIP712TypedData(obj) && isHash(obj);