Hi everyone, I’ve been experiencing some weird problems with the testnet server.
Server info: (I just created this server but all servers have the same issue.)
https://skrazr9qzo4e.usemoralis.com:2053/server
Here is the list of the problems:
Problem 1: Our server stops sync after some events are emitted then I have to delete and create another server because if I just reset it does not sync anymore.
Problem 2: Our server is showing up an error about CORS that is intermittent too, but when it happens I have to reset the server
Problem 3: Whenever I reset the server the events stop firing then I have to delete and create a new server.
ps: we are rushing with our development to go live with the application by the middle of the month and it seems impossible with the events not firing, server error and etc. Please, I would appreciate some help to resolve this issue immediately.
My contract is:
rinkeby: 0x26d1059Ae5E6F3c3Ea0162a385D430eb54e9CDd2
I usually set up all events accordingly and it works the first time, maybe for some time but after it stops again and I start getting errors.
Here is my cloud function code:
Moralis.Cloud.define("getUserByUsername", async (request) => {
try {
const User = Moralis.Object.extend("User");
const query = new Moralis.Query(User);
request.params.username &&
query.equalTo("username", request.params.username);
request.params.address &&
query.equalTo("ethAddress", request.params.address);
const results = await query.first({ useMasterKey: true });
return results;
} catch (e) {
logger.info(`INFO (getUserByUsername) -> ${JSON.stringify(e)}`);
}
});
Moralis.Cloud.define("getFilePath", async (request) => {
try {
const ItemsPublished = Moralis.Object.extend("ItemsPublished");
let query = new Moralis.Query(ItemsPublished);
query.equalTo("objectId", request.params.objectId);
query.equalTo("from", request.user.get("ethAddress"));
let result = await query.first();
if (result) {
let fileData = await fetchIPFSDoc(result.get("uri"), false);
return {
file: fileData.properties.file,
};
}
} catch (e) {
logger.info(`INFO (getFilePath) -> ${JSON.stringify(e)}`);
}
});
Moralis.Cloud.define("getAuthorRoyalties", async (request) => {
try {
const itemData = Moralis.Object.extend("ItemsPublished");
const query = new Moralis.Query(itemData);
query.equalTo("objectId", request.params.objectId);
query.equalTo("from", request.user.get("ethAddress"));
let result = await query.first();
return {
authorRoyalties: result.get("authorRoyalties"),
};
} catch (e) {
logger.info(`Error getAuthorRoyalties -> ${e}`);
}
});
Moralis.Cloud.define("getItem", async (request) => {
try {
const Items = Moralis.Object.extend("ItemsPublished");
let query = new Moralis.Query(Items);
query.equalTo("objectId", request.params.objectId);
request.params.status && query.equalTo("status", request.params.status);
// Count query
if (request.params.onlyCount) {
const queryResults = await query.count();
return queryResults;
}
const queryResults = await query.first({ useMasterKey: true });
return {
objectId: queryResults.id,
id: queryResults.attributes.uid,
owner: await getUser(null, false, null, queryResults.attributes.owner_of),
data: {
metadata: await fetchIPFSDoc(queryResults.attributes.uri),
likes: {
count: queryResults.attributes.likes
? queryResults.attributes.likes.length
: 0,
isLiked:
queryResults.attributes.likes &&
queryResults.attributes.likes.includes(
request.user.get("ethAddress")
),
},
views: {
count: queryResults.attributes.views
? queryResults.attributes.views.length
: 0,
isViewed:
queryResults.attributes.views &&
queryResults.attributes.views.includes(
request.user.get("ethAddress")
),
},
},
};
} catch (e) {
logger.info(`INFO (getItem) -> ${JSON.stringify(e)}`);
}
});
Moralis.Cloud.define("getItemsPublished", async (request) => {
try {
const ItemsPublished = Moralis.Object.extend("ItemsPublished");
let query = new Moralis.Query(ItemsPublished);
// Apply filters if existing
query = await applyFilters(
request,
query,
request.params,
"ItemsPublished"
);
// Count query
if (request.params.onlyCount) {
const queryResults = await query.count();
return queryResults;
}
const queryResults = await query.find({ useMasterKey: true });
const results = [];
for (let i = 0; i < queryResults.length; ++i) {
logger.info(`QUERY RESULTS -> ${JSON.stringify(queryResults[i])}`);
results.push({
objectId: queryResults[i].id,
id: queryResults[i].attributes.uid,
owner: await getUser(
null,
false,
null,
queryResults[i].attributes.owner_of
),
data: {
metadata: await fetchIPFSDoc(queryResults[i].attributes.uri),
likes: {
count: queryResults[i].attributes.likes
? queryResults[i].attributes.likes.length
: 0,
isLiked:
queryResults[i].attributes.likes &&
queryResults[i].attributes.likes.includes(
request.user.get("ethAddress")
),
},
views: {
count: queryResults[i].attributes.views
? queryResults[i].attributes.views.length
: 0,
isViewed:
queryResults[i].attributes.views &&
queryResults[i].attributes.views.includes(
request.user.get("ethAddress")
),
},
},
});
}
return results;
} catch (e) {
logger.info(`INFO (getItemsPublished) -> ${e}`);
}
});
Moralis.Cloud.define("getCollections", async (request) => {
try {
let query = new Moralis.Query("Collection");
// Apply filters if existing
query = await applyFilters(request, query, request.params);
// Count query
if (request.params.onlyCount) {
const queryResults = await query.count();
return queryResults;
}
const queryResults = await query.find({ useMasterKey: true });
const results = [];
for (let i = 0; i < queryResults.length; ++i) {
results.push({
user: await getUser(
null,
false,
queryResults[i].attributes.user.id,
null
),
item: queryResults[i],
likesCount: queryResults[i].attributes.likes
? queryResults[i].attributes.likes.length
: 0,
isLiked:
queryResults[i].attributes.likes &&
queryResults[i].attributes.likes.length
? await isLiked(
queryResults[i],
queryResults[i].attributes.likes,
true,
request.user
)
: false,
});
}
return results;
} catch (e) {
logger.info(`INFO (getCollections) -> ${JSON.stringify(e)}`);
}
});
/* After and Before Save functions */
Moralis.Cloud.afterSave("ItemsPublished", (request) => {
try {
logger.info(`Event fired (ItemsPublished) -> ${JSON.stringify(request)}`);
updateItemTable(request, {
status: "New",
author: request.object.get("from").toLowerCase(),
buyer: request.object.get("from").toLowerCase(),
isSold: false,
updateOnly: true,
eventName: "publish",
}).then((response) => {
logger.info(`(ItemsPublished) -> ${response}`);
});
// Update only - never create a new item | Publish(address from, uint256 id, uint256 quantity, address tokenAddress, uint256 authorRoyalties, string uri) | DONE
} catch (e) {
logger.info(`Error - ItemsPublished -> ${e}`);
}
});
Moralis.Cloud.beforeSave("ItemsOnSale", async (request) => {
try {
logger.info(`Event fired (ItemsOnSale) -> ${JSON.stringify(request)}`);
let response = await updateItemTable(request, {
status: "OnSale",
isSold: true,
updateOnly: true,
eventName: "addselling",
});
// Update only - never create a new item | AddSelling(address owner, uint256 id, uint256 amount, string uri) | DONE
logger.info(`(ItemsOnSale)-> ${JSON.stringify(response)}`);
} catch (e) {
logger.info(`Error - ItemsOnSale -> ${e}`);
}
});
Moralis.Cloud.beforeSave("ItemsTransfer", async (request) => {
try {
logger.info(`Event fired (ItemsTransfer) -> ${JSON.stringify(request)}`);
let response = await updateItemTable(request, {
buyer: request.object.get("buyer").toLowerCase(),
seller: request.object.get("seller").toLowerCase(),
amount: request.object.get("amount"),
isSold: false,
amountLeft: request.object.get("amountLeft"),
eventName: "transfer",
});
// Update or Create | Transfer(address seller, address buyer, uint256 id, uint256 amount, uint256 amountLeft)
// use cases
/*
seller has 1 item and transfers 1 item to buyer = seller(0) buyer(1) -> update owner_of
seller has 10 items and transfer 5 items to buyer = seller(5) buyer(5) -> create new item with owner_of, quantity(amount),
*/
logger.info(`(ItemsTransfer)-> ${JSON.stringify(response)}`);
} catch (e) {
logger.info(`Error - ItemsTransfer -> ${e}`);
}
});
/* Email functions */
Moralis.Cloud.define("EmailVerification", function (request) {
Moralis.Cloud.sendEmail({
to: request.params.email,
subject: "Email verification",
templateId: "d-edf86fc111ab46f5bd5ad98e3ccfa459",
dynamic_template_data: {
email: request.params.email,
},
});
});
Moralis.Cloud.define("EmailContact", function (request) {
Moralis.Cloud.sendEmail({
to: "[email protected]",
subject: "Email verification",
templateId: "d-9061a8be14974eb9b2940a749de2adb7",
dynamic_template_data: {
email: request.params.email,
body: request.params.body,
},
});
});
async function updateItemTable(
request,
{
status,
isSold = undefined,
updateOnly = false,
author,
buyer,
seller,
amount,
amountLeft,
eventName,
}
) {
try {
const query = new Moralis.Query("ItemsPublished");
request.object.get("uid") &&
query.equalTo("uid", request.object.get("uid"));
request.object.get("uri") &&
query.equalTo("uri", request.object.get("uri"));
request.object.get("tokenAddress") &&
query.equalTo("tokenAddress", request.object.get("tokenAddress"));
seller && query.equalTo("owner_of", seller);
let itemPublished = await query.first({ useMasterKey: true });
if (!itemPublished) {
logger.info(`Item Not FOUND -> ${JSON.stringify(itemPublished)}`);
return;
}
if (updateOnly) {
const ItemsPublishedObj = Moralis.Object.extend("ItemsPublished");
const ipobj = new ItemsPublishedObj();
ipobj.set("objectId", itemPublished.id);
author && eventName === "publish" && ipobj.set("author", author);
status && ipobj.set("status", status);
buyer && ipobj.set("owner_of", buyer);
isSold !== undefined && ipobj.set("isSold", isSold);
let resp = await ipobj.save();
logger.info(`update [updateItemTable] -> ${JSON.stringify(resp)}`);
return;
}
const ItemsPublishedObj = Moralis.Object.extend("ItemsPublished");
const ipobj = new ItemsPublishedObj();
//update if amount left is 0, but if amount zero is bigger than 0 we need to create a new item
logger.info(`Amount Left (${amountLeft}) [updateItemTable]`);
if (Number(amountLeft) === 0) {
ipobj.set("objectId", itemPublished.id);
} else {
logger.info(`new [updateItemTable]`);
}
logger.info(`amountLeft -> ${Number(amountLeft)}`);
ipobj.set("uid", itemPublished.get("uid"));
ipobj.set("uri", itemPublished.get("uri"));
amount && ipobj.set("quantity", amount);
status && ipobj.set("status", status);
isSold !== undefined && ipobj.set("isSold", isSold);
author && ipobj.set("author", author);
buyer && ipobj.set("owner_of", buyer);
let response = await ipobj.save();
if (response)
logger.info(`save [updateItemTable] -> ${JSON.stringify(response)}`);
else logger.info(`something happened [updateItemTable]`);
} catch (e) {
logger.info(
`Err to updateItemTable -> ${
typeof e === "object" ? JSON.stringify(e) : e
}`
);
}
}
async function getUser(
username,
wholeObject = false,
userId,
userAddress = null
) {
// Query userDwriter class
let userQuery = new Moralis.Query(Moralis.User);
logger.info(`username: ${username}`);
logger.info(`byDwriterId: ${userId}`);
logger.info(`ethAddress -> ${userAddress}`);
userId && userQuery.equalTo("objectId", userId);
username && userQuery.equalTo("username", username);
userAddress && userQuery.equalTo("ethAddress", userAddress.toLowerCase());
let result = await userQuery.first({
useMasterKey: true,
});
logger.info(`result [getUser] -> ${JSON.stringify(result)}`);
if (!result) {
return {};
}
if (wholeObject) {
logger.info(`ENTROU AQUI`);
return result;
}
return {
id: result.get("objectId"),
username: result.get("username"),
verified: result.get("verified"),
image: result.get("profilePic") || "",
displayName: result.get("displayName") || "",
bio: result.get("bio") || "",
address: {
blockchain: "ethereum",
value: result.get("ethAddress") || "",
},
social_media: {
twitter: result.get("twitter") || "",
instagram: result.get("instagram") || "",
discord: result.get("discord") || "",
},
updated_at: result.get("updatedAt"),
created_at: result.get("createdAt"),
};
}
async function isLiked(data, likes, isCollection, user) {
if (!likes) return false;
let isliked = false;
const queryLikes = new Moralis.Query(
isCollection ? "CollectionLikes" : "ItemLikes"
);
if (!user) {
return false;
}
queryLikes.equalTo("user", user.get("ethAddress"));
isCollection
? queryLikes.equalTo("collection", data.attributes.collection_id)
: queryLikes.equalTo("uid", data.attributes.uid);
logger.info(`TEST -> ${data.attributes.uid}`);
logger.info(`TEST 2 -> ${user.get("ethAddress")}`);
const queryLikesResults = await queryLikes.find();
logger.info(`QueryLikeResults ${JSON.stringify(queryLikesResults)}`);
if (!queryLikesResults || (queryLikesResults && !queryLikesResults.length)) {
return false;
}
queryLikesResults.filter((result) => {
if (likes && likes.includes(result.get("user"))) {
isliked = true;
} else {
isliked = false;
}
});
return isliked;
}
async function isViewed(data, views, isCollection, user) {
if (!views) return false;
let isViewed = false;
const queryViews = new Moralis.Query(
isCollection ? "CollectionViews" : "ItemViews"
);
if (!user) {
return false;
}
queryViews.equalTo("user", user.get("ethAddress"));
isCollection
? queryViews.equalTo("collection", data.attributes.collection_id)
: queryViews.equalTo("uid", data.attributes.uid);
logger.info(`UID -> ${data.attributes.uid}`);
const queryViewsResults = await queryViews.find();
logger.info(`queryViewsResults 123 -> ${JSON.stringify(queryViewsResults)}`);
if (!queryViewsResults || (queryViewsResults && !queryViewsResults.length)) {
return false;
}
queryViewsResults.filter((result) => {
if (views && views.includes(result.get("user"))) {
isViewed = true;
} else {
isViewed = false;
}
});
return isViewed;
}
// Filters
async function applyFilters(
request,
query,
{
search,
category,
tag,
status,
startDate,
endDate,
minPrice,
maxPrice,
limit,
page,
ownedByUser,
sortByLikes,
belongsToCollection,
collectionID,
filterByUsername,
},
tableToSearch
) {
if (belongsToCollection && collectionID) {
query.equalTo("collection_id", collectionID);
query.include("collection");
logger.info(`Collection ID -> ${collectionID}`);
}
logger.info(`filterByUsername: ${filterByUsername}`);
logger.info(`OwnedbyUser: ${ownedByUser}`);
if (filterByUsername || ownedByUser) {
query.equalTo("owner_of", request.user.get("ethAddress"));
}
sortByLikes && query.descending("likes");
// //search && query.fullText("title", search);
// //category && query.equalTo("category", category);
// //tag && query.containedIn("tags", [tag]);
// salesType && query.equalTo("salesType", salesType);
status && query.equalTo("status", status);
startDate &&
query.greaterThan("createdAt", new Date(startDate.replace(/-/gm, "/")));
endDate && query.lessThan("createdAt", new Date(endDate.replace(/-/gm, "/")));
// //minPrice && query.greaterThan("price", parseInt(minPrice));
// //maxPrice && query.lessThan("price", parseInt(maxPrice));
limit && query.limit(page !== 0 ? limit * (page + 1) : limit);
logger.info(`Filters applied.`);
return query;
}
async function fetchIPFSDoc(ipfsHash, hiddenFile = true) {
const url = `https://ipfs.moralis.io:2053/ipfs/${ipfsHash}`;
let data;
await Moralis.Cloud.httpRequest({
url: url,
}).then(
function (httpResponse) {
// success
data = JSON.parse(httpResponse.text);
hiddenFile && delete data["properties"]["file"];
},
function (httpResponse) {
// error
logger.info("Request failed with response code " + httpResponse.status);
}
);
//logger.info(`Httpresponse 2 -> ${data}`);
return data;
}
Here are the logs: (i don’t know why this is in loop (afterSave function))