@biconomy/abstractjs
Version:
SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.
104 lines • 4.07 kB
JavaScript
import { parseAbi, publicActions } from "viem";
import { DUMMY_SIGNATURE } from "../index.js";
/**
* ERC-7739 support detection constants
* @see https://eips.ethereum.org/EIPS/eip-7739#support-detection
*/
const ERC7739_DETECTION_HASH = "0x7739773977397739773977397739773977397739773977397739773977397739";
const ERC7739_MAGIC_PREFIX = "0x77390"; // bytes4(0x7739000x) where x is version
export const toValidator = (parameters) => {
const { deInitData = "0x", type = "validator", signer, walletClient, data = "0x", module, erc7739VersionSupported_, ...rest } = parameters;
if (walletClient && !walletClient.account) {
throw new Error("Account should be defined in the wallet client provided to the `toValidator`");
}
let _erc7739VersionSupported = erc7739VersionSupported_;
const erc7739VersionSupported = async () => {
if (_erc7739VersionSupported === undefined) {
// If walletClient is available, detect ERC-7739 version from contract
if (walletClient) {
_erc7739VersionSupported = await detectErc7739Version(walletClient, module);
}
else {
// No walletClient available, can not detect ERC-7739 support
// assume no ERC-7739 support
_erc7739VersionSupported = 0;
}
}
return _erc7739VersionSupported;
};
const signMessage = async (message) => {
if (signer) {
return await signer.signMessage({ message });
}
return await walletClient.signMessage({
account: walletClient.account,
message
});
};
const signUserOperationHash = async (hash) => {
return await signMessage({ raw: hash });
};
const signTypedData = async (typedData) => {
if (signer) {
return await signer.signTypedData(typedData);
}
return await walletClient.signTypedData({
account: walletClient.account,
...typedData
});
};
const signMessageErc7739 = (_message, _verifierDomain) => {
throw new Error("Erc7739 PersonalSign flow is not supported by this module");
};
const signTypedDataErc7739 = (_typedData, _verifierDomain) => {
throw new Error("Erc7739 TypedDataSign flow is not supported by this module");
};
return {
deInitData,
data,
module,
address: module,
...(signer ? { signer } : { walletClient: walletClient }),
type,
getStubSignature: async () => DUMMY_SIGNATURE,
signMessage,
signUserOperationHash,
signTypedData,
erc7739VersionSupported,
signMessageErc7739,
signTypedDataErc7739,
...rest
};
};
/**
* Detects ERC-7739 version support by calling isValidSignature on the module contract
* @param walletClient - The wallet client to use for the read call
* @param moduleAddress - The address of the module contract
* @returns The ERC-7739 version number (0 if not supported)
*/
const detectErc7739Version = async (walletClient, moduleAddress) => {
try {
const client = walletClient.extend(publicActions);
const result = await client.readContract({
address: moduleAddress,
abi: parseAbi([
"function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4)"
]),
functionName: "isValidSignature",
args: [ERC7739_DETECTION_HASH, "0x"]
});
// Check if result matches magic prefix 0x77390xxx
if (typeof result === "string" &&
result.toLowerCase().startsWith(ERC7739_MAGIC_PREFIX)) {
// Extract version from last digit (e.g., 0x77390001 -> version 1)
const versionHex = result.slice(-1);
return Number.parseInt(versionHex, 16);
}
return 0;
}
catch {
// If the call fails, module doesn't support ERC-7739
return 0;
}
};
//# sourceMappingURL=toValidator.js.map