As of 9 Oct 2022 the current available tutorials/guides regarding using Smart contract event syncs similar to the older Moralis SDK 1 Workflow is inconsistent (so I don’t say inexistent). Please take note that this guide has been written in a hurry because of lack of time. The reason why I posted this here is to save some frustration I went through so you don’t have to.
WARNING
The code shown here has NOT been tested for production environment and is only a way of achieving functionality similar to the current Event syncs. It also lacks the mapping of tags->tableName and with the code shown below, the tableName is actually the event’s name (as defined in Smart contract). Also the :any
is used widely here to suppress Typescript errors.
Introduction
Moralis offers a repo with a sample installation of parse-server with integrations to the EvmApi functions of the new SDK which is available at https://github.com/MoralisWeb3/Moralis-JS-SDK/tree/main/demos/parse-server-migration but which does not out-of-the-box support the Streams API.
How to integrate
A patch has been made and it is available in this repo: https://github.com/MoralisWeb3/parse-server-moralis-streams but this patch is NOT compatible with the previous repo, although they are linked in the same tutorial inside the Docs. (bummer!)
In order to get Streams API working with the first repo, the one where the EvmApi is already integrated you have to do the following:
You have to install either Moralis SDK v1 or the Parse SDK (which MoralisSDKv1 is build over) and connect to the parse-server from the parse-server (sounds like a paradox…right?).
You can read more about it here where you will also find instructions on how to connect to the parse-server.
Inside the express app which servers a foundation for the parse-server and for parse-dashboard (if you have it installed) you have to add some post routes for each of your webhooks.
Example route:
app.post('/webhooks/test', async (req: any, res: any) => {
console.log(req.body);
try {
verifySignature(req, config.MORALIS_API_KEY);
const { data, tagName, eventName }: any = parseEventData(req);
console.log(data);
await parseUpdate(`SFS_${eventName}`, data);
} catch (e) {
console.log(e);
}
res.send('ok');
});
export async function parseUpdate(tableName: string, object: any) {
// Check if object exists in db
const query = new Parse.Query(tableName);
query.equalTo('transaction_hash', object.transaction_hash);
const result = await query.first({ useMasterKey: true });
if (result) {
// Loop through object's keys
for (const key in object) {
result.set(key, object[key]);
}
return result?.save(null, { useMasterKey: true });
} else {
// Create new object
const newObject = new Parse.Object(tableName);
for (const key in object) {
newObject.set(key, object[key]);
}
return newObject.save(null, { useMasterKey: true });
}
}
The verifySignature function code is available here, you gotta get it from here and put it somewhere inside your code, I put it at ./src/helpers/utils.ts
.
The parseEventData is a function with the following signature:
export function parseEventData(req: any) {
try {
const updates: any = {};
for (const log of req.body.logs) {
const abi = req.body.abis[log.streamId];
if (abi) {
const { filter, update, eventName } = realtimeUpsertParams(abi, log, req.body.confirmed, req.body.block);
return { data: update, tagName: log.tag, eventName };
}
}
} catch (e: any) {
console.log(e);
}
}
The realtimeUpsertParams
function code is available here. To make the parse-dashboard work with values outputted by this function you need to remove the numberDecimal support until the properly patched parse-dashboard is released by the Moralis team.
Rewriting the decodeWithEthers
function available in the same file to not include the numberDecimal stuff fixes the dashboard issue.