[SOLVED] Send tokens from cloud function

Hi guys,
I’d like to send tokens to my userses’ addresses from backend, paying gas, so they won’t see anything but the result
I’ve written a Cloud function to do so, but it gives me error…
I don’t know if it’s the best way to do this, I accept any suggestion

Moralis.Cloud.define("transfer", async (request) => {

  const web3 = Moralis.web3ByChain("0x13881")	//mumbai testnet
  const contract = new web3.eth.Contract(CONTRACT_ABI, CONTRACT_ADDRESS);
  
  const address = request.param.address;
  const amount = request.param.amout;
  
  let data = await contract.methods.transfer(address, amount).encodeABI();
  let nGas = web3.utils.toHex(100000);

  let txObj = {
    "gas": nGas,
    "to": USER_ADDRESS,
    "value": 0x0,
    "data": data,
    "from": CONTRACT_OWNER
  }
  
  await web3.eth.accounts.signTransaction(txObj, PRIVATE_KEY, function(err, signedTx) {
    if (err)
      return {"KO", err}
    else
    {
      await web3.eth.sendSignedTransaction(signedTx.rawTransaction, function(err, res) {
        if (err)
          return {"KO", err}
        else{
		  return {"OK", res}          
        }
      });
    }
  });

}

This is the error in dashboard log

2022-06-09T09:05:56.067Z - Error: Invalid function: "transfer"
    at handleCloudFunction (/moralis-server/lib/Routers/FunctionsRouter.js:201:13)
    at /moralis-server/lib/PromiseRouter.js:85:20
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
2022-06-09T09:00:36.590Z - SyntaxError: Unexpected identifier
    at customUserPlugin (/moralis-server/cloud/main.js:157:26)
    at /moralis-server/lib/cloud-code/plugins/index.js:144:15
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Object.initialize (/moralis-server/lib/cloud-code/plugins/index.js:133:3)

There are some syntax errors in the cloud code. You can check the code for syntax errors in any js console and then try again.

following it. I also have to do a similar thing but I am very new to JS.
@johnversus @Joe_Doe how can I call my cloud function from the corn job. I am very confused about it. For example, if I have to do the same, to send tokens to my users from the backend every month so it must be scheduled as ā€˜Job’ on moralis server but how can I call a cloud function from the Job. If you know this please help me

you can set a cloud function as a job directly, or call any other function defined in cloud code from a job

1 Like

SyntaxError found, it was the return object…{ result: ā€œKOā€, msg: err }

The other error is still there

2022-06-09T12:49:49.103Z - Error: Invalid function: "transfer"
    at handleCloudFunction (/moralis-server/lib/Routers/FunctionsRouter.js:201:13)
    at /moralis-server/lib/PromiseRouter.js:85:20
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

This is my JavaScript call

const params = {
		address: ADDRESS_TO,
		amount: 10
	}

console.log(await Moralis.Cloud.run("transfer", params));

Did you fix this one?

I tried to run in browser console, it gave me this error.

from this line

And also a bracket ) at end of the code is missing.

I guess fixing these should solve the invalid function error.

Now, fixed some errors, edit a bit my function, but the result is the same

Moralis.Cloud.define("transfer", async (request) => {

  const ABI =abi;
  const CONTRACT_ADDRESS = address;
  const CONTRACT_OWNER = owner;
  const PRIVATE_KEY = private_key;
  
  const web3 = Moralis.web3ByChain("0x13881")	//mumbai testnet
  const contract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS);
  
  const address = request.params.address;
  const amount = request.params.amount;
  
  let data = await contract.methods.transfer(address, amount).encodeABI();
  let nGas = web3.utils.toHex(100000);

  let txObj = {
    "gas": nGas,
    "to": CONTRACT_ADDRESS,
    "value": 0x0,
    "data": data,
    "from": CONTRACT_OWNER
  }
  
  await web3.eth.accounts.signTransaction(txObj, PRIVATE_KEY, function(err, signedTx) {
    if (err)
      return {
			result: "KO",
			msg: err
		}
    else
    {
       web3.eth.sendSignedTransaction(signedTx.rawTransaction, function(err, res) {
        if (err)
          return {
				result: "KO",
				msg: err
			}
        else{
		  return {
				result: "OK",
				msg: res
			}                  
        }
      });
    }
  });
});

Error

Error: Invalid function: "transfer"
    at handleCloudFunction (/moralis-server/lib/Routers/FunctionsRouter.js:201:13)
    at /moralis-server/lib/PromiseRouter.js:85:20
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

Did you fix all this variables ??
If not, try fix them all

yes, in my code I’ve the real data, here to be shorter I’ve just written those names

What about making this value: "0x00"

Just edited the value in 0x00.
It gives no error in dashboard logs, but I get these two messages

2022-06-09T15:12:33.659Z - Ran cloud function transfer for user undefined with:
  Input: {"address":"0x8eDc8d607931a870392FF61fDaa6F4001d0cF97c","amount":10}
  Result: undefined
2022-06-09T15:12:33.578Z - Ran cloud function getPluginSpecs for user undefined with:
  Input: {}
  Result: [{"name":"coreservices","functions":["getConfig","setConfig","getWeb3ApiToken","track","getOrganization","setOrganization","getEventSyncs","addEventSync","removeEventSync","listEventSyncStatus","getAddressSyncs","addAddressSync","removeAddressSync","listAddressSyncStatus","getProviders","setChains","getChains"]}]

You can verify the transfer on the explorer if it went through

I had to delete the ā€œawaitā€ instruction before the web3.eth.accounts.signTransaction call to make is works!
I can see the transaction on the explorer, but I get always ā€œundefinedā€ as result in my JavaScript call
I’ve tried changing the code, but everytime I touch something it gives me tons of errors, CORS etc…
If anyone knows how to get a valid response I’ll appreciate, otherwise I’ll go on this way

Anyway thank you all for your support

You can replace this with this

    let signedTransaction = await web3.eth.accounts.signTransaction(
      txObj,
      privateKey
    );

    logger.info(signedTransaction);

    const sentTx = await web3.eth.sendSignedTransaction(
      signedTransaction.raw || signedTransaction.rawTransaction
    );

    logger.info(sentTx);

    logger.info("Transaction Hash", sentTx.transactionHash);
    return { status: true, sentTx };

Where const logger = Moralis.Cloud.getLogger();

@qudusayo, it works!!!
I don’t know how to thank you

This is my entire function, in case could be of any help to someone else

Moralis.Cloud.define("transfer", async (request) => {
  
  const ABI = contract_abi;
  const CONTRACT_ADDRESS = contract_address;
  const CONTRACT_OWNER = contract_owner;
  const PRIVATE_KEY = private_key;
  
  //const logger = Moralis.Cloud.getLogger();
  
  const web3 = Moralis.web3ByChain("0x13881")	//mumbai testnet
  const contract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS);
  
  const address = request.params.address;
  const amount = request.params.amount;
  
  let data = contract.methods.transfer(address, amount).encodeABI();
  let nGas = web3.utils.toHex(100000);

  let txObj = {
    "gas": nGas,
    "to": CONTRACT_ADDRESS,
    "value": 0x00,
    "data": data,
    "from": CONTRACT_OWNER
  }
  
  let signedTx;
  try {
  	signedTx = await web3.eth.accounts.signTransaction(txObj, PRIVATE_KEY);
  } catch(err) {
    return {
      result: "KO",
      msg: err
    };
  }
  
  //logger.info(signedTx);
  
  let sentTx;
  try {
    sentTx = await web3.eth.sendSignedTransaction(
      signedTx.rawTransaction  || signedTx.raw);
  } catch(err) {	  
    return {
      result: "KO",
      msg: err
    };
  }
  
  //logger.info(sentTx);
  //logger.info("Transaction Hash", sentTx.transactionHash);
  
  return {
    result: "OK",
    msg: sentTx.transactionHash
  };

  });

2 Likes