UNPKG

@biconomy/modules

Version:

This package provides different validation modules/plugins for ERC4337 compatible modular account

227 lines 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BatchedSessionRouterModule = void 0; const ethers_1 = require("ethers"); const common_1 = require("@biconomy/common"); const utils_1 = require("ethers/lib/utils"); const Constants_1 = require("./utils/Constants"); const BaseValidationModule_1 = require("./BaseValidationModule"); const SessionKeyManagerModule_1 = require("./SessionKeyManagerModule"); class BatchedSessionRouterModule extends BaseValidationModule_1.BaseValidationModule { /** * This constructor is private. Use the static create method to instantiate SessionKeyManagerModule * @param moduleConfig The configuration for the module * @returns An instance of SessionKeyManagerModule */ constructor(moduleConfig) { super(moduleConfig); this.version = "V1_0_0"; this.mockEcdsaSessionKeySig = "0x73c3ac716c487ca34bb858247b5ccf1dc354fbaabdd089af3b2ac8e78ba85a4959a2d76250325bd67c11771c31fccda87c33ceec17cc0de912690521bb95ffcb1b"; /** * Method to create session data for any module. The session data is used to create a leaf in the merkle tree * @param leavesData The data of one or more leaves to be used to create session data * @returns The session data */ this.createSessionData = async (leavesData) => { return this.sessionKeyManagerModule.createSessionData(leavesData); }; } /** * Asynchronously creates and initializes an instance of SessionKeyManagerModule * @param moduleConfig The configuration for the module * @returns A Promise that resolves to an instance of SessionKeyManagerModule */ static async create(moduleConfig) { var _a; const instance = new BatchedSessionRouterModule(moduleConfig); if (moduleConfig.moduleAddress) { instance.moduleAddress = moduleConfig.moduleAddress; } else if (moduleConfig.version) { const moduleAddr = Constants_1.BATCHED_SESSION_ROUTER_MODULE_ADDRESSES_BY_VERSION[moduleConfig.version]; if (!moduleAddr) { throw new Error(`Invalid version ${moduleConfig.version}`); } instance.moduleAddress = moduleAddr; instance.version = moduleConfig.version; } else { instance.moduleAddress = Constants_1.DEFAULT_BATCHED_SESSION_ROUTER_MODULE; // Note: in this case Version remains the default one } instance.sessionManagerModuleAddress = (_a = moduleConfig.sessionManagerModuleAddress) !== null && _a !== void 0 ? _a : Constants_1.DEFAULT_SESSION_KEY_MANAGER_MODULE; if (!moduleConfig.sessionKeyManagerModule) { // generate sessionModule const sessionModule = await SessionKeyManagerModule_1.SessionKeyManagerModule.create({ moduleAddress: instance.sessionManagerModuleAddress, smartAccountAddress: moduleConfig.smartAccountAddress, nodeClientUrl: moduleConfig.nodeClientUrl, storageType: moduleConfig.storageType, }); instance.sessionKeyManagerModule = sessionModule; } else { instance.sessionKeyManagerModule = moduleConfig.sessionKeyManagerModule; instance.sessionManagerModuleAddress = moduleConfig.sessionKeyManagerModule.getAddress(); } return instance; } /** * This method is used to sign the user operation using the session signer * @param userOp The user operation to be signed * @param sessionParams Information about all the sessions to be used to sign the user operation which has a batch execution * @returns The signature of the user operation */ async signUserOpHash(userOpHash, params) { var _a; const sessionParams = params === null || params === void 0 ? void 0 : params.batchSessionParams; if (!sessionParams || sessionParams.length === 0) { throw new Error("Session parameters are not provided"); } const sessionDataTupleArray = []; // signer must be the same for all the sessions const sessionSigner = sessionParams[0].sessionSigner; const signature = await sessionSigner.signMessage((0, utils_1.arrayify)(userOpHash)); for (const sessionParam of sessionParams) { if (!sessionParam.sessionSigner) { throw new Error("Session signer is not provided."); } const sessionDataTuple = []; let sessionSignerData; if (sessionParam.sessionID) { sessionSignerData = await this.sessionKeyManagerModule.sessionStorageClient.getSessionData({ sessionID: sessionParam.sessionID, }); } else if (sessionParam.sessionValidationModule) { sessionSignerData = await this.sessionKeyManagerModule.sessionStorageClient.getSessionData({ sessionValidationModule: sessionParam.sessionValidationModule, sessionPublicKey: await sessionSigner.getAddress(), }); } else { throw new Error("sessionID or sessionValidationModule should be provided."); } sessionDataTuple.push(sessionSignerData.validUntil); sessionDataTuple.push(sessionSignerData.validAfter); sessionDataTuple.push(sessionSignerData.sessionValidationModule); sessionDataTuple.push(sessionSignerData.sessionKeyData); const leafDataHex = (0, utils_1.hexConcat)([ (0, utils_1.hexZeroPad)(ethers_1.ethers.utils.hexlify(sessionSignerData.validUntil), 6), (0, utils_1.hexZeroPad)(ethers_1.ethers.utils.hexlify(sessionSignerData.validAfter), 6), (0, utils_1.hexZeroPad)(sessionSignerData.sessionValidationModule, 20), sessionSignerData.sessionKeyData, ]); const proof = this.sessionKeyManagerModule.merkleTree.getHexProof(ethers_1.ethers.utils.keccak256(leafDataHex)); sessionDataTuple.push(proof); sessionDataTuple.push((_a = sessionParam.additionalSessionData) !== null && _a !== void 0 ? _a : "0x"); sessionDataTupleArray.push(sessionDataTuple); } // Generate the padded signature const paddedSignature = utils_1.defaultAbiCoder.encode(["address", "tuple(uint48,uint48,address,bytes,bytes32[],bytes)[]", "bytes"], [this.getSessionKeyManagerAddress(), sessionDataTupleArray, signature]); return paddedSignature; } /** * Update the session data pending state to active * @param param The search param to find the session data * @param status The status to be updated * @returns */ async updateSessionStatus(param, status) { this.sessionKeyManagerModule.sessionStorageClient.updateSessionStatus(param, status); } /** * @remarks This method is used to clear all the pending sessions * @returns */ async clearPendingSessions() { this.sessionKeyManagerModule.sessionStorageClient.clearPendingSessions(); } /** * @returns SessionKeyManagerModule address */ getAddress() { return this.moduleAddress; } /** * @returns SessionKeyManagerModule address */ getSessionKeyManagerAddress() { return this.sessionManagerModuleAddress; } /** * @remarks This is the version of the module contract */ async getSigner() { throw new Error("Method not implemented."); } /** * @remarks This is the dummy signature for the module, used in buildUserOp for bundler estimation * @returns Dummy signature */ async getDummySignature(params) { var _a; const sessionParams = params === null || params === void 0 ? void 0 : params.batchSessionParams; if (!sessionParams || sessionParams.length === 0) { throw new Error("Session parameters are not provided"); } const sessionDataTupleArray = []; // if needed we could do mock signature over userOpHashAndModuleAddress // signer must be the same for all the sessions const sessionSigner = sessionParams[0].sessionSigner; for (const sessionParam of sessionParams) { if (!sessionParam.sessionSigner) { throw new Error("Session signer is not provided."); } const sessionDataTuple = []; let sessionSignerData; if (sessionParam.sessionID) { sessionSignerData = await this.sessionKeyManagerModule.sessionStorageClient.getSessionData({ sessionID: sessionParam.sessionID, }); } else if (sessionParam.sessionValidationModule) { sessionSignerData = await this.sessionKeyManagerModule.sessionStorageClient.getSessionData({ sessionValidationModule: sessionParam.sessionValidationModule, sessionPublicKey: await sessionSigner.getAddress(), }); } else { throw new Error("sessionID or sessionValidationModule should be provided."); } sessionDataTuple.push(sessionSignerData.validUntil); sessionDataTuple.push(sessionSignerData.validAfter); sessionDataTuple.push(sessionSignerData.sessionValidationModule); sessionDataTuple.push(sessionSignerData.sessionKeyData); const leafDataHex = (0, utils_1.hexConcat)([ (0, utils_1.hexZeroPad)(ethers_1.ethers.utils.hexlify(sessionSignerData.validUntil), 6), (0, utils_1.hexZeroPad)(ethers_1.ethers.utils.hexlify(sessionSignerData.validAfter), 6), (0, utils_1.hexZeroPad)(sessionSignerData.sessionValidationModule, 20), sessionSignerData.sessionKeyData, ]); const proof = this.sessionKeyManagerModule.merkleTree.getHexProof(ethers_1.ethers.utils.keccak256(leafDataHex)); sessionDataTuple.push(proof); sessionDataTuple.push((_a = sessionParam.additionalSessionData) !== null && _a !== void 0 ? _a : "0x"); sessionDataTupleArray.push(sessionDataTuple); } // Generate the padded signature const paddedSignature = utils_1.defaultAbiCoder.encode(["address", "tuple(uint48,uint48,address,bytes,bytes32[],bytes)[]", "bytes"], [this.getSessionKeyManagerAddress(), sessionDataTupleArray, this.mockEcdsaSessionKeySig]); const dummySig = ethers_1.ethers.utils.defaultAbiCoder.encode(["bytes", "address"], [paddedSignature, this.getAddress()]); return dummySig; } /** * @remarks Other modules may need additional attributes to build init data */ async getInitData() { throw new Error("Method not implemented."); } /** * @remarks This Module dont have knowledge of signer. So, this method is not implemented */ async signMessage(message) { common_1.Logger.log("message", message); throw new Error("Method not implemented."); } } exports.BatchedSessionRouterModule = BatchedSessionRouterModule; //# sourceMappingURL=BatchedSessionRouterModule.js.map