@layr-labs/hourglass-performer
Version:
TypeScript SDK for building Hourglass AVS performers
260 lines • 9.65 kB
JavaScript
"use strict";
// SolidityWorker base class for TypeChain integration and ABI handling
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SolidityWorkerUtils = exports.JsonSolidityWorker = exports.SolidityWorker = void 0;
const iWorker_1 = require("./iWorker");
const abiUtils_1 = require("../utils/abiUtils");
/**
* SolidityWorker base class with TypeChain integration
*
* Generic parameters:
* - TContract: TypeChain-generated contract interface
* - TFunction: Function name from the contract
*/
class SolidityWorker extends iWorker_1.BaseWorker {
constructor(config) {
super();
// Use default config if none provided (for simple usage)
this.config = {
autoDetectPayload: true,
strictMode: false,
abi: [],
functionName: 'handleTask',
...config,
};
if (this.config.abi.length > 0) {
this.abiCodec = new abiUtils_1.AbiCodec(this.config.abi);
}
}
/**
* Validate task with ABI decoding
*/
async validateTask(task) {
await super.validateTask(task);
// Validate ABI decoding
try {
this.decodeTaskPayload(task.payload);
}
catch (error) {
if (this.config.strictMode) {
throw new Error(`ABI validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
// In non-strict mode, just warn
console.warn(`ABI validation warning: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Handle task with automatic ABI decoding/encoding
*/
async handleTask(task) {
try {
// Decode payload using ABI (if available)
const decodedParams = this.abiCodec ? this.decodeTaskPayload(task.payload) : this.parsePayload(task.payload);
// Call user-implemented handler with decoded parameters
const result = await this.handleSolidityTask(decodedParams);
// Encode result using ABI (if available)
const encodedResult = this.abiCodec ? this.encodeTaskResult(result) : this.encodePayload(result);
return this.createResponse(task.taskId, encodedResult);
}
catch (error) {
throw new Error(`Solidity task handling failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Simple start method for one-line usage
*/
async start(port = 8080) {
const { PerformerServer } = await Promise.resolve().then(() => __importStar(require('../server/performerServer')));
const server = new PerformerServer(this, {
port,
timeout: 10000,
debug: true,
});
// Set up graceful shutdown
server.setupGracefulShutdown();
try {
await server.start();
console.log(`🚀 Performer is running on port ${port}!`);
}
catch (error) {
console.error('❌ Failed to start server:', error);
process.exit(1);
}
}
/**
* Decode task payload using ABI
*/
decodeTaskPayload(payload) {
if (this.config.autoDetectPayload) {
const detection = abiUtils_1.PayloadAutoDecoder.decode(payload);
if (detection.format === 'abi' && this.abiCodec) {
return this.abiCodec.decodeFunctionCall(this.config.functionName, payload);
}
else if (detection.format === 'json') {
// For JSON payloads, try to map to function parameters
return this.mapJsonToAbiParams(detection.data);
}
else {
// For other formats, pass through as raw data
return { data: payload };
}
}
else {
// Direct ABI decoding
return this.abiCodec ? this.abiCodec.decodeFunctionCall(this.config.functionName, payload) : { data: payload };
}
}
/**
* Encode task result using ABI
*/
encodeTaskResult(result) {
return this.abiCodec ? this.abiCodec.encodeFunctionResult(this.config.functionName, result) : this.encodePayload(result);
}
/**
* Map JSON data to ABI function parameters
*/
mapJsonToAbiParams(jsonData) {
if (!this.abiCodec) {
return jsonData;
}
const funcInfo = this.abiCodec.getFunctionInfo(this.config.functionName);
if (!funcInfo) {
throw new Error(`Function ${this.config.functionName} not found in ABI`);
}
const mapped = {};
for (const param of funcInfo.inputs) {
const paramName = param.name || `param${funcInfo.inputs.indexOf(param)}`;
if (jsonData.hasOwnProperty(paramName)) {
mapped[paramName] = jsonData[paramName];
}
}
return mapped;
}
/**
* Get function information from ABI
*/
getFunctionInfo() {
return this.abiCodec ? this.abiCodec.getFunctionInfo(this.config.functionName) : undefined;
}
/**
* Get all available functions from ABI
*/
getAllFunctions() {
return this.abiCodec ? this.abiCodec.getAllFunctions() : [];
}
/**
* Manually decode payload (for advanced use cases)
*/
manualDecode(payload) {
return this.abiCodec ? this.abiCodec.decodeFunctionCall(this.config.functionName, payload) : { data: payload };
}
/**
* Manually encode result (for advanced use cases)
*/
manualEncode(result) {
return this.abiCodec ? this.abiCodec.encodeFunctionResult(this.config.functionName, result) : this.encodePayload(result);
}
}
exports.SolidityWorker = SolidityWorker;
/**
* Simplified SolidityWorker for JSON-based configuration
*/
class JsonSolidityWorker extends iWorker_1.BaseWorker {
constructor(abi, functionName) {
super();
this.abiCodec = new abiUtils_1.AbiCodec(abi);
this.functionName = functionName;
}
async handleTask(task) {
try {
// Auto-detect and decode payload
const detection = abiUtils_1.PayloadAutoDecoder.decode(task.payload);
let decodedParams;
if (detection.format === 'abi') {
decodedParams = this.abiCodec.decodeFunctionCall(this.functionName, task.payload);
}
else if (detection.format === 'json') {
decodedParams = detection.data;
}
else {
decodedParams = { data: task.payload };
}
// Call user handler
const result = await this.handleDecodedTask(decodedParams);
// Encode result
let encodedResult;
if (typeof result === 'object' && result !== null) {
encodedResult = this.abiCodec.encodeFunctionResult(this.functionName, result);
}
else {
encodedResult = this.abiCodec.encodeFunctionResult(this.functionName, { result });
}
return this.createResponse(task.taskId, encodedResult);
}
catch (error) {
throw new Error(`JSON Solidity task handling failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}
exports.JsonSolidityWorker = JsonSolidityWorker;
/**
* Utility functions for SolidityWorker
*/
class SolidityWorkerUtils {
/**
* Create a simple worker from ABI and handler function
*/
static createFromAbi(abi, functionName, handler) {
return new (class extends JsonSolidityWorker {
async handleDecodedTask(params) {
return handler(params);
}
})(abi, functionName);
}
/**
* Create a worker with automatic TypeChain integration
*/
static createTyped(config, handler) {
return new (class extends SolidityWorker {
async handleSolidityTask(params) {
return handler(params);
}
})(config);
}
}
exports.SolidityWorkerUtils = SolidityWorkerUtils;
// Decorator removed - use SolidityWorker class directly for better type safety
//# sourceMappingURL=solidityWorker.js.map