@zerodev/sdk
Version:
A utility library for working with ERC-4337
301 lines • 13.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.toKernelPluginManager = exports.isKernelPluginManager = void 0;
const semver_1 = require("semver");
const viem_1 = require("viem");
const actions_1 = require("viem/actions");
const encodeModuleInstallCallData_js_1 = require("../../accounts/kernel/utils/account/ep0_6/encodeModuleInstallCallData.js");
const constants_js_1 = require("../../constants.js");
const kernel_js_1 = require("../../types/kernel.js");
const getKernelV3Nonce_js_1 = require("../kernel/utils/account/ep0_7/getKernelV3Nonce.js");
const accountMetadata_js_1 = require("../kernel/utils/common/accountMetadata.js");
const getActionSelector_js_1 = require("../kernel/utils/common/getActionSelector.js");
const getEncodedPluginsData_js_1 = require("../kernel/utils/plugins/ep0_6/getEncodedPluginsData.js");
const getPluginsEnableTypedData_js_1 = require("../kernel/utils/plugins/ep0_6/getPluginsEnableTypedData.js");
const getEncodedPluginsData_js_2 = require("../kernel/utils/plugins/ep0_7/getEncodedPluginsData.js");
const getPluginsEnableTypedData_js_2 = require("../kernel/utils/plugins/ep0_7/getPluginsEnableTypedData.js");
const isPluginInitialized_js_1 = require("../kernel/utils/plugins/ep0_7/isPluginInitialized.js");
function isKernelPluginManager(plugin) {
return plugin?.getPluginEnableSignature !== undefined;
}
exports.isKernelPluginManager = isKernelPluginManager;
async function toKernelPluginManager(client, { sudo, regular, hook, pluginEnableSignature, validatorInitData, action, validAfter = 0, validUntil = 0, entryPoint, kernelVersion, chainId, isPreInstalled = false }) {
if ((sudo && !(0, semver_1.satisfies)(kernelVersion, sudo?.supportedKernelVersions)) ||
(regular && !(0, semver_1.satisfies)(kernelVersion, regular?.supportedKernelVersions))) {
throw new Error("Either sudo or/and regular validator version mismatch. Update to latest plugin package and use the proper plugin version");
}
let pluginEnabled = isPreInstalled;
const activeValidator = regular || sudo;
if (!activeValidator) {
throw new Error("One of `sudo` or `regular` validator must be set");
}
action = {
selector: action?.selector ?? (0, getActionSelector_js_1.getActionSelector)(entryPoint.version),
address: action?.address ?? viem_1.zeroAddress
};
if (entryPoint.version === "0.7" &&
(action.address.toLowerCase() !== viem_1.zeroAddress.toLowerCase() ||
action.selector.toLowerCase() !==
(0, getActionSelector_js_1.getActionSelector)(entryPoint.version).toLowerCase()) &&
kernelVersion === "0.3.0") {
action.hook = {
address: action.hook?.address ?? constants_js_1.ONLY_ENTRYPOINT_HOOK_ADDRESS
};
}
if (!action) {
throw new Error("Action data must be set");
}
const getSignatureData = async (accountAddress, selector, userOpSignature = "0x") => {
if (!action) {
throw new Error("Action data must be set");
}
if (entryPoint.version === "0.6") {
if (regular) {
if (pluginEnabled) {
return kernel_js_1.ValidatorMode.plugin;
}
if (await isPluginEnabled(accountAddress, selector)) {
return kernel_js_1.ValidatorMode.plugin;
}
const enableSignature = await getPluginEnableSignature(accountAddress);
if (!enableSignature) {
throw new Error("Enable signature not set");
}
return (0, getEncodedPluginsData_js_1.getEncodedPluginsData)({
accountAddress,
enableSignature,
action,
validator: regular,
validUntil,
validAfter
});
}
else if (sudo) {
return kernel_js_1.ValidatorMode.sudo;
}
else {
throw new Error("One of `sudo` or `regular` validator must be set");
}
}
if (regular) {
if (pluginEnabled) {
return userOpSignature;
}
if (await isPluginEnabled(accountAddress, action.selector)) {
return userOpSignature;
}
const enableSignature = await getPluginEnableSignature(accountAddress);
return (0, getEncodedPluginsData_js_2.getEncodedPluginsData)({
enableSignature,
userOpSignature,
action,
enableData: await regular.getEnableData(accountAddress),
hook
});
}
else if (sudo) {
return userOpSignature;
}
else {
throw new Error("One of `sudo` or `regular` validator must be set");
}
};
const isPluginEnabled = async (accountAddress, selector) => {
if (isPreInstalled)
return true;
if (!action) {
throw new Error("Action data must be set");
}
if (!regular)
throw new Error("regular validator not set");
if (entryPoint.version === "0.6") {
return regular.isEnabled(accountAddress, selector);
}
const isEnabled = (await regular.isEnabled(accountAddress, action.selector)) ||
(await (0, isPluginInitialized_js_1.isPluginInitialized)(client, accountAddress, regular.address));
if (isEnabled) {
pluginEnabled = true;
}
return isEnabled;
};
const getPluginEnableSignature = async (accountAddress) => {
if (!action) {
throw new Error("Action data must be set");
}
if (pluginEnableSignature)
return pluginEnableSignature;
if (!sudo)
throw new Error("sudo validator not set -- need it to enable the validator");
if (!regular)
throw new Error("regular validator not set");
const { version } = await (0, accountMetadata_js_1.accountMetadata)(client, accountAddress, kernelVersion);
if (!chainId) {
chainId = client.chain?.id ?? (await (0, actions_1.getChainId)(client));
}
let ownerSig;
if (entryPoint.version === "0.6") {
const typeData = await (0, getPluginsEnableTypedData_js_1.getPluginsEnableTypedData)({
accountAddress,
chainId,
kernelVersion: version ?? kernelVersion,
action,
validator: regular,
validUntil,
validAfter
});
ownerSig = await sudo.signTypedData(typeData);
pluginEnableSignature = ownerSig;
return ownerSig;
}
const validatorNonce = await (0, getKernelV3Nonce_js_1.getKernelV3Nonce)(client, accountAddress);
const typedData = await (0, getPluginsEnableTypedData_js_2.getPluginsEnableTypedData)({
accountAddress,
chainId,
kernelVersion: version,
action,
hook,
validator: regular,
validatorNonce
});
ownerSig = await sudo.signTypedData(typedData);
pluginEnableSignature = ownerSig;
return ownerSig;
};
const getIdentifier = (isSudo = false) => {
const validator = (isSudo ? sudo : regular) ?? activeValidator;
return (0, viem_1.concat)([
constants_js_1.VALIDATOR_TYPE[validator.validatorType],
validator.getIdentifier()
]);
};
const getPluginsEnableTypedData = async (accountAddress) => {
if (!action) {
throw new Error("Action data must be set");
}
if (!sudo)
throw new Error("sudo validator not set -- need it to enable the validator");
if (!regular)
throw new Error("regular validator not set");
const { version } = await (0, accountMetadata_js_1.accountMetadata)(client, accountAddress, kernelVersion);
const validatorNonce = await (0, getKernelV3Nonce_js_1.getKernelV3Nonce)(client, accountAddress);
if (!chainId) {
chainId = client.chain?.id ?? (await (0, actions_1.getChainId)(client));
}
const typedData = await (0, getPluginsEnableTypedData_js_2.getPluginsEnableTypedData)({
accountAddress,
chainId,
kernelVersion: version,
action,
validator: regular,
validatorNonce
});
return typedData;
};
return {
sudoValidator: sudo,
regularValidator: regular,
activeValidatorMode: sudo && !regular ? "sudo" : "regular",
...activeValidator,
hook,
getIdentifier,
encodeModuleInstallCallData: async (accountAddress) => {
if (!action) {
throw new Error("Action data must be set");
}
if (!regular)
throw new Error("regular validator not set");
if (entryPoint.version === "0.6") {
return await (0, encodeModuleInstallCallData_js_1.encodeModuleInstallCallData)({
accountAddress,
selector: action.selector,
executor: action.address,
validator: regular?.address,
validUntil,
validAfter,
enableData: await regular.getEnableData(accountAddress)
});
}
throw new Error("EntryPoint v0.7 not supported yet");
},
signUserOperation: async (userOperation) => {
const userOpSig = await activeValidator.signUserOperation(userOperation);
if (entryPoint.version === "0.6") {
return (0, viem_1.concatHex)([
await getSignatureData(userOperation.sender, userOperation.callData.toString().slice(0, 10)),
userOpSig
]);
}
return await getSignatureData(userOperation.sender, userOperation.callData.toString().slice(0, 10), userOpSig);
},
getAction: () => {
if (!action) {
throw new Error("Action data must be set");
}
return action;
},
getValidityData: () => ({
validAfter,
validUntil
}),
getStubSignature: async (userOperation) => {
const userOpSig = await activeValidator.getStubSignature(userOperation);
if (entryPoint.version === "0.6") {
return (0, viem_1.concatHex)([
await getSignatureData(userOperation.sender, userOperation.callData.toString().slice(0, 10)),
userOpSig
]);
}
return await getSignatureData(userOperation.sender, userOperation.callData.toString().slice(0, 10), userOpSig);
},
getNonceKey: async (accountAddress = viem_1.zeroAddress, customNonceKey = 0n) => {
if (!action) {
throw new Error("Action data must be set");
}
if (entryPoint.version === "0.6") {
if (customNonceKey > viem_1.maxUint192) {
throw new Error("Custom nonce key must be equal or less than maxUint192 for 0.6");
}
return await activeValidator.getNonceKey(accountAddress, customNonceKey);
}
if (customNonceKey > viem_1.maxUint16)
throw new Error("Custom nonce key must be equal or less than 2 bytes(maxUint16) for v0.7");
const validatorMode = !regular ||
(await isPluginEnabled(accountAddress, action.selector))
? constants_js_1.VALIDATOR_MODE.DEFAULT
: constants_js_1.VALIDATOR_MODE.ENABLE;
const validatorType = regular
? constants_js_1.VALIDATOR_TYPE[regular.validatorType]
: constants_js_1.VALIDATOR_TYPE.SUDO;
const encoding = (0, viem_1.pad)((0, viem_1.concatHex)([
validatorMode,
validatorType,
(0, viem_1.pad)(activeValidator.getIdentifier(), {
size: 20,
dir: "right"
}),
(0, viem_1.pad)((0, viem_1.toHex)(await activeValidator.getNonceKey(accountAddress, customNonceKey)), {
size: 2
})
]), { size: 24 });
const encodedNonceKey = BigInt(encoding);
return encodedNonceKey;
},
getPluginEnableSignature,
getPluginsEnableTypedData,
getValidatorInitData: async () => {
if (validatorInitData)
return validatorInitData;
return {
validatorAddress: sudo?.address ?? activeValidator.address,
enableData: (await sudo?.getEnableData()) ??
(await activeValidator.getEnableData()),
identifier: (0, viem_1.pad)(getIdentifier(true), { size: 21, dir: "right" })
};
},
signUserOperationWithActiveValidator: async (userOperation) => {
return activeValidator.signUserOperation(userOperation);
}
};
}
exports.toKernelPluginManager = toKernelPluginManager;
//# sourceMappingURL=toKernelPluginManager.js.map
;