Set balance value using afterSave trigger

I am trying to create a field “value” in the _AddressSyncStatus collection for each entry after it has been synced using the plugin. The afterSave gets triggered according to the log, but the “value” column including the web3 value doesnt get saved.

Am I doing something wrong? The logs dont output any error.

Moralis.Cloud.afterSave("_AddressSyncStatus", async request => {
  logger.info("afterSave _AddressSyncStatus called");
  const addressObj = request.object;
  const ethBalance = await Moralis.Web3API.account.getNativeBalance({
    address: addressObj.get("address")
  });
  addressObj.set("value", ethBalance);
  addressObj.save();
});

2022-03-20T15:54:25.878Z - Ran cloud function coreservices_getConfig for user undefined with:
  Input: {}
  Result: {"status":200,"data":{"success":true,"result":{"providers":[{"chain":"Eth","name":"Mainnet","network":"mainnet","exchange":"eth","chainId":"0x1","lookups":["eth","mainnet","0x1"],"token":{"name":"Ether","symbol":"ETH"},"httpProviderUrl":"eth/mainnet","maxRecordsPerCategory":50,"userSync":true}],"addressSyncs":[{"chainId":"0x1","address":"0xf977814e90da44bfa03b6295a0616a897441acec","syncHistorical":false,"key":"0xf977814e90da44bfa03b6295a0616a897441acec_1"},{"chainId":"0x1","address":"0xdf9eb223bafbe5c5271415c75aecd68c21fe3d7f","syncHistorical":false,"key":"0xdf9eb223bafbe5c5271415c75aecd68c21fe3d7f_1"},{"chainId":"0x1","address":"0x42e0ab4619c7be98f7c9cd7b57ba02362ad79459","syncHistorical":true,"key":"0x42e0ab4619c7be98f7c9cd7b57ba02362ad79459_1"},{"chainId":"0x1","address":"0xd10c833f4305E1053a64Bc738c550381f48104Ca","syncHistorical":false,"key":"0xd10c833f4305e1053a64bc738c550381f48104ca_1"},{"chainId":"0x1","address":"0x7edd7d8bb062c9883400e498cb7538a008281468","syncHistorical":true... (truncated)
2022-03-20T15:54:25.365Z - Ran cloud function coreservices_getWeb3ApiToken for user undefined with:
  Input: {}
  Result: {"status":200,"data":{"success":true,"result":"O148899.1647791665327.0x34e08231a42f6e544ac563de6333c1da2462b59e6e096897ba79d04617705a29"}}
2022-03-20T15:54:25.294Z - afterSave _AddressSyncStatus called

You could try to use master key for that .save

I thought masterkey is automatically available when calling .save from cloud functions?

with this it doesnt work either, no error but no “value” column created.

Moralis.Cloud.afterSave("_AddressSyncStatus", async request => {
  logger.info("afterSave _AddressSyncStatus called");
  const addressObj = request.object;
  const ethBalance = await Moralis.Web3API.account.getNativeBalance({
    address: addressObj.get("address")
  });
  addressObj.set("value", ethBalance);
  addressObj.save({useMasterKey:true});
});

There is a different syntax for using the master key for .save. The second parameter is the master key and not the first. You can find examples in documentation

thanks with .save(null,{useMasterKey:true}) it works. What is weird that it doesnt output any error even tho I surrounded it with a try catch even. Maybe thats something to add for easier debugging in the future.

1 Like

I deleted all rows and modified the code to use the Moralis.units functions. Now the “value” column again doesnt get created and filled in the database.

Moralis.Cloud.afterSave("_AddressSyncStatus", async request => {
  try {
    logger.info(
      "afterSave _AddressSyncStatus " + JSON.stringify(request.object)
    );

    const balance = await Moralis.Web3API.account.getNativeBalance({
      address: request.object.get("address")
    });

    const ethBalance = await Moralis.Cloud.units({
      method: "fromWei",
      value: balance["balance"]
    });

    logger.info(JSON.stringify(ethBalance));
    addressObj.set("value", ethBalance);
    return await addressObj.save(null, { useMasterKey: true });
  } catch (error) {
    logger.info(error);
  }
});

The log shows the output of the Unit function, but its not getting saved again. Any idea why?

2022-03-20T17:46:43.012Z - Ran cloud function coreservices_getConfig for user undefined with:
  Input: {}
  Result: {"status":200,"data":{"success":true,"result":{"providers":[{"chain":"Eth","name":"Mainnet","network":"mainnet","exchange":"eth","chainId":"0x1","lookups":["eth","mainnet","0x1"],"token":{"name":"Ether","symbol":"ETH"},"httpProviderUrl":"eth/mainnet","maxRecordsPerCategory":50,"userSync":true}],"addressSyncs":[{"chainId":"0x1","address":"0x25eaff5b179f209cf186b1cdcbfa463a69df4c45","syncHistorical":false,"key":"0x25eaff5b179f209cf186b1cdcbfa463a69df4c45_1"},{"chainId":"0x1","address":"0xa7e4fecddc20d83f36971b67e13f1abc98dfcfa6","syncHistorical":false,"key":"0xa7e4fecddc20d83f36971b67e13f1abc98dfcfa6_1"},{"chainId":"0x1","address":"0xeddf8eb4984cc27407a568cae1c78a1ddb0c2c1b","syncHistorical":false,"key":"0xeddf8eb4984cc27407a568cae1c78a1ddb0c2c1b_1"},{"chainId":"0x1","address":"0xfd898a0f677e97a9031654fc79a27cb5e31da34a","syncHistorical":false,"key":"0xfd898a0f677e97a9031654fc79a27cb5e31da34a_1"}],"eventSyncs":[]}}}
2022-03-20T17:46:42.439Z - undefined
2022-03-20T17:46:42.437Z - "150000"
2022-03-20T17:46:42.354Z - Ran cloud function coreservices_getWeb3ApiToken for user undefined with:
  Input: {}
  Result: {"status":200,"data":{"success":true,"result":"O148899.1647798402351.0x62afc435a2604665b5d5cafead30091ffa386be89989b80bd7c6b22c87fe4de9"}}
2022-03-20T17:46:42.334Z - afterSave _AddressSyncStatus {"address":"0xeddf8eb4984cc27407a568cae1c78a1ddb0c2c1b","chain":"Eth","updatedAt":"2022-03-20T17:46:42.323Z"}

Maybe it is a different type like string and number. Make sure to not enter in infinite loops by saving same object that will trigger after save again

the column doesnt exist anymore, I deleted the column and all documents in the tables, so it has no type cause its not existing.

Try to add it back then

Will try that. Is there any say of deleting all rows from a collection table from code?

I found bulk queries in the documentation, but they are all for example that take filters. What if I dont have any filters because I want to delete them all?

you can delete from code too, from dashboard interface it is also easy to delete all the rows

value column gets created now, but I run into a new error now unfortunatly.

The address I sync using the plugin gets populated into the _AddressSyncStatus collection with the “value” of undefined while I get another entry into that table without any other data BUT the value data of for example “0.07”.

the afterSave function below generates 2 Objects into the table with 2 different object IDs, although I get the object from request.object and then set the value of it before saving it. What am I doing wrong?

Moralis.Cloud.afterSave("_AddressSyncStatus", async request => {
  try {
    logger.info(
      "afterSave _AddressSyncStatus " + JSON.stringify(request.object)
    );

    const object = request.object;

    const balance = await Moralis.Web3API.account.getNativeBalance({
      address: object.get("address")
    });

    const ethBalance = await Moralis.Cloud.units({
      method: "fromWei",
      value: balance["balance"]
    });

    logger.info(JSON.stringify(ethBalance));
    
    object.set("value", ethBalance);

    return await object.save(null, { useMasterKey: true });
  } catch (error) {
    logger.info(error);
  }
});

I still don’t know how this code doesn’t run in an infinite loop. how do you know when to stop from updating an object?

what do you mean, I call the watchAddress function of Moralis, after that is done it saves it and calls afterSave, from which I just set the value field and save. Thats no infinite loop. But with my code I get 2 objects saved everytime with 2 different objectits.

when I get request.object and set a value to that and save it, it shouldnt create a new one in my understanding,

I don’t know why it creates 2 objects, but also I don’t know why object.save doesn’t call again afterSave hook and this way entering in an infinite loop

yes thats weird, here its not the case but otherwise how would anyone be able to update fields after object creation if it would cause an infinite loop

one can check if some particular flag was already set for example

it looks like your code enters in an infinite loop but it exits fast with an error on the second iteration

there is no error in any log showing up tho. Before I didnt have duplicates, now I have. Thats all pretty confusing

try to print that address in logs to see what you get