Set balance value using afterSave trigger

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

its printing the same address I am trying to sync.
I am now trying to use beforeSave rather than afterSave which gives me only 1 correct value. What I dont know tho is, if beforeSave gets called while data is synced by moralis, or only once in time of existence before the very first save?

If for example tomorrow a transaction happens from a synced wallet, will beforeSave gets called again before data gets updated, or only afterSave?

beforeSave and afterSave will be called both on an update

the problem with beforeSave is that if an error happened in that function then that object is not saved any more

Ok yes thats probably not desireable, did not manage to fix the duplicate entries using afterSave tho

in the working exmample, you had

addressObj.set("value", ethBalance); but didn’t seem that it was defined in that function

True, that was my bad which I noticed afterwards. I replaced that object everywhere with request.object and that still ended up creating 2 objects in the database with 2 different object ids like this

objectId: xy, value: undefined
objectId: yz: value: 0.7

maybe you can run a query, to get the object, and then to update it, in that afterSave