UNPKG

@biconomy/abstractjs

Version:

SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.

99 lines 3.96 kB
import { isHex, pad, publicActions, toFunctionSelector, toHex } from "viem"; import { ERROR_MESSAGES } from "../../account/index.js"; /** * Parses a reference value into a 32-byte hex string. * Handles various input types including Ethereum addresses, numbers, booleans, and raw hex values. * * @param referenceValue - The value to convert to hex * @returns A 32-byte hex string (66 characters including '0x' prefix) * * @throws {Error} If the resulting hex string is invalid or not 32 bytes */ export function parseReferenceValue(referenceValue) { let result; // Handle 20-byte Ethereum address if (isHex(referenceValue) && referenceValue.length === 42) { // Remove '0x' prefix, pad to 32 bytes (64 characters) on the left, then add '0x' prefix back result = `0x${"0".repeat(24)}${referenceValue.slice(2)}`; } else if (referenceValue?.raw) { result = referenceValue?.raw; } else if (typeof referenceValue === "bigint") { result = pad(toHex(referenceValue), { size: 32 }); } else if (typeof referenceValue === "number") { result = pad(toHex(BigInt(referenceValue)), { size: 32 }); } else if (typeof referenceValue === "boolean") { result = pad(toHex(referenceValue), { size: 32 }); } else if (isHex(referenceValue)) { // review result = referenceValue; } else if (typeof referenceValue === "string") { result = pad(referenceValue, { size: 32 }); } else { // (typeof referenceValue === "object") result = pad(toHex(referenceValue), { size: 32 }); } if (!isHex(result) || result.length !== 66) { throw new Error(ERROR_MESSAGES.INVALID_HEX); } return result; } /** * Extracts and validates the active module from a client's account. * * @param client - The viem Client instance with an optional modular smart account * @returns The active module from the account * * @throws {Error} If no module is currently activated */ export const parseModule = (client) => { const activeModule = client?.account?.getModule(); if (!activeModule) { throw new Error(ERROR_MESSAGES.MODULE_NOT_ACTIVATED); } return activeModule; }; export const isPermitSupported = async (walletClient, tokenAddress) => { try { const client = walletClient.extend(publicActions); // Define all selectors const permitSelector = toFunctionSelector("permit(address,address,uint256,uint256,uint8,bytes32,bytes32)"); const domainSeparatorSelector = "0x3644e515"; // keccak256("DOMAIN_SEPARATOR()") const noncesSelector = "0x7ecebe00"; // keccak256("nonces(address)") // Helper function to check function existence const checkPermitEnabled = async (selector, padding = "") => { return client .call({ to: tokenAddress, data: `${selector}${padding}` }) .then(() => true) .catch((error) => { // For permit function, we check if it's a revert due to params, not function missing if (selector === permitSelector) { return (error.message.includes("revert") && !error.message.includes("function selector")); } return false; }); }; // Create the calls to check for each function const [hasPermit, hasDomainSeparator, hasNonces] = await Promise.all([ checkPermitEnabled(permitSelector, "0".repeat(64)), checkPermitEnabled(domainSeparatorSelector), checkPermitEnabled(noncesSelector, `000000000000000000000000${"0".repeat(40)}`) ]); return hasPermit && hasDomainSeparator && hasNonces; } catch (err) { console.error("Error checking permit support:", err); return false; } }; //# sourceMappingURL=Helpers.js.map