Example autotask fails to run with typescript compilation

Hello, I'm trying to get the example task executed by a relayer, but the Defender UI shows the following error, independent of the content of the scripts.

:computer: Environment

Using

  • defender-serverless v1.0.4
  • defender-autotask-client v1.43.0
  • typescript v5.0.3
  • webpack v5.78.0

:memo:Details

Error:
userHandler is not a function

Logs:

END RequestId: dd3081fa-a03e-4a52-bd98-3700ea8db46a
AUTOTASK COMPLETE
2023-05-11T00:00:27.395Z	ERROR	Invoke Error 	{"errorType":"TypeError","errorMessage":"userHandler is not a function","stack":["TypeError: userHandler is not a function","    at Runtime.handler (/opt/nodejs/autotask-wrapper.js:83:26)","    at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1086:29)"]}

:1234: Code to reproduce

import { BaseProvider } from '@ethersproject/providers';
import { DefenderRelaySigner, DefenderRelayProvider} from 'defender-relay-client/lib/ethers';
import { RelayerParams } from 'defender-relay-client/lib/relayer';
import { Signer } from 'ethers';

// Entrypoint for the autotask
export async function handler(credentials: RelayerParams) {
  // Use the credentials to initialize a DefenderRelayProvider and DefenderRelaySigner
  // They can be used as ethers.js providers and signers
  const provider = new DefenderRelayProvider(credentials);
  const signer = new DefenderRelaySigner(credentials, provider, { speed: 'fast' });
  // Run the ethers script logic with the provider and signer
  await ethersScript(provider, signer)
}

// Script logic
export async function ethersScript(provider: BaseProvider, signer: Signer) {
  console.log(`Assciated relayer address is: ${await signer.getAddress()}`)

  // TODO: Implement tx transmission logic using ethers js library
  // Use provider and signer for querying or sending txs from ethers, for example...
  // const contract = new ethers.Contract(ADDRESS, ABI, signer);
  // await contract.ping();
  console.log(`Implement me!`)
}

Hi @Honesch,

I tried to reproduce your error but was unsuccessful. I used the provided snippet and built it with https://github.com/OpenZeppelin/defender-autotask-examples/tree/master/webpack. I then manually created an Autotask with the generated code, and it worked correctly.

I also tested it with updated versions that match the ones you mentioned, and it worked as well.

Additionally, I deployed the generated bundle with defender-serverless, and it worked without any issues.

The error you posted occurs when the handler function is not exported from the generated bundle. Could you please verify that the handler is exported from your bundle? Also, make sure that the local bundle matches the uploaded code.

You can try to create Autotask manually with generated bundle to check the results without involving defender-serverless. Once you verify that everything works, we can attempt to deploy it with defender-serverless. One potential error could be an incorrect path to the generated bundle, resulting in the wrong code being uploaded during Autotask creation.

I hope this helps.

Best regards,
Zeljko

Hi @zeljko,

Thanks for the detailed response. The deployment via defender-serverless seems to work fine. I validated the local bundle to be the exact same as the deployed code.

Following is the autotask code, directly copied from the Defender UI under "Edit code". To my understanding, the handler function is correctly exported at the line exports.handler = handler;. However, the error persists, when manually executing the task.

/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ "defender-relay-client/lib/ethers":
/*!***************************************************!*\
  !*** external "defender-relay-client/lib/ethers" ***!
  \***************************************************/
/***/ ((module) => {

module.exports = require("defender-relay-client/lib/ethers");

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
var exports = __webpack_exports__;
/*!***********************************!*\
  !*** ./src/example-task/index.ts ***!
  \***********************************/

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ethersScript = exports.handler = void 0;
const ethers_1 = __webpack_require__(/*! defender-relay-client/lib/ethers */ "defender-relay-client/lib/ethers");
// Entrypoint for the autotask
async function handler(credentials) {
    // Use the credentials to initialize a DefenderRelayProvider and DefenderRelaySigner
    // They can be used as ethers.js providers and signers
    const provider = new ethers_1.DefenderRelayProvider(credentials);
    const signer = new ethers_1.DefenderRelaySigner(credentials, provider, { speed: 'fast' });
    // Run the ethers script logic with the provider and signer
    await ethersScript(provider, signer);
}
exports.handler = handler;
// Script logic
async function ethersScript(provider, signer) {
    console.log(`Assciated relayer address is: ${await signer.getAddress()}`);
    // TODO: Implement tx transmission logic using ethers js library
    // Use provider and signer for querying or sending txs from ethers, for example...
    // const contract = new ethers.Contract(ADDRESS, ABI, signer);
    // await contract.ping();
    console.log(`Implement me!`);
}
exports.ethersScript = ethersScript;

})();

/******/ })()
;
//# sourceMappingURL=index.js.map

Hi @Honesch

I have tried to run provided code and I experienced same error.

After inspecting code I I found that functions are not exported.

Sample test: Save code to test.js file. Create index.js file and try to import with require test.js file. Object is empty.

It will work if you add module.exports = __webpack_exports__; at the bottom of file.


  })();
  module.exports = __webpack_exports__;

  /******/ })()
  ;
  //# sourceMappingURL=index.js.map

Seems like that webpack configuration needs to be modified in order to make it to work.

Let's try with setting

libraryTarget: "commonjs2"

Best,
Zeljko

1 Like