@etherspot/prime-sdk
Version:
Etherspot Prime (Account Abstraction) SDK
79 lines (78 loc) • 3.41 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserOperationEventListener = void 0;
const utils_1 = require("ethers/lib/utils");
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)('aa.listener');
const DEFAULT_TRANSACTION_TIMEOUT = 10000;
class UserOperationEventListener {
constructor(resolve, reject, entryPoint, sender, userOpHash, nonce, timeout) {
var _a;
this.resolve = resolve;
this.reject = reject;
this.entryPoint = entryPoint;
this.sender = sender;
this.userOpHash = userOpHash;
this.nonce = nonce;
this.timeout = timeout;
this.resolved = false;
this.boundLisener = this.listenerCallback.bind(this);
setTimeout(() => {
this.stop();
this.reject(new Error('Timed out'));
}, (_a = this.timeout) !== null && _a !== void 0 ? _a : DEFAULT_TRANSACTION_TIMEOUT);
}
start() {
const filter = this.entryPoint.filters.UserOperationEvent(this.userOpHash);
setTimeout(async () => {
const res = await this.entryPoint.queryFilter(filter, 'latest');
if (res.length > 0) {
void this.listenerCallback(res[0]);
}
else {
this.entryPoint.once(filter, this.boundLisener);
}
}, 100);
}
stop() {
this.entryPoint.off('UserOperationEvent', this.boundLisener);
}
async listenerCallback(...param) {
var _a;
const event = arguments[arguments.length - 1];
if (event.args == null) {
console.error('got event without args', event);
return;
}
if (event.args.userOpHash !== this.userOpHash) {
console.log(`== event with wrong userOpHash: sender/nonce: event.${event.args.sender}@${event.args.nonce.toString()}!= userOp.${this.sender}@${parseInt((_a = this.nonce) === null || _a === void 0 ? void 0 : _a.toString())}`);
return;
}
const transactionReceipt = await event.getTransactionReceipt();
transactionReceipt.transactionHash = this.userOpHash;
debug('got event with status=', event.args.success, 'gasUsed=', transactionReceipt.gasUsed);
if (!event.args.success) {
await this.extractFailureReason(transactionReceipt);
}
this.stop();
this.resolve(transactionReceipt);
this.resolved = true;
}
async extractFailureReason(receipt) {
debug('mark tx as failed');
receipt.status = 0;
const revertReasonEvents = await this.entryPoint.queryFilter(this.entryPoint.filters.UserOperationRevertReason(this.userOpHash, this.sender), receipt.blockHash);
if (revertReasonEvents[0] != null) {
let message = revertReasonEvents[0].args.revertReason;
if (message.startsWith('0x08c379a0')) {
message = utils_1.defaultAbiCoder.decode(['string'], '0x' + message.substring(10)).toString();
}
debug(`rejecting with reason: ${message}`);
this.reject(new Error(`UserOp failed with reason: ${message}`));
}
}
}
exports.UserOperationEventListener = UserOperationEventListener;