PatrickAlphaC / nextjs-nft-marketplace-moralis-fcc

44 stars 50 forks source link

update events synchronisation with latest Moralis v2 self hosted database #22

Open BTT21000 opened 1 year ago

BTT21000 commented 1 year ago

Moralis has recently moved from the moralist hosted database to self hosted database as per shown below: https://docs.moralis.io/docs/migrating-from-v1-to-v2 https://www.youtube.com/watch?v=l2qTyc-V9cM Would it be possible to have a tutorial, video update, or repo addition to update our full stack nextjs-nft-marketplace-moralis-fcc accordingly? Basically the stack now requires to use a parse server, Moralis streams to listen to events, and a self hosted MongoDB. Thank you

PatrickAlphaC commented 1 year ago

Yes... I'll add this to my todo list. Thank you.

BTT21000 commented 1 year ago

Thank you very much Patrick! For your info Moralis has just released a tutorial about "How to Set Up Self-Hosted Server and Listen to Blockchain Events in Realtime": https://www.youtube.com/watch?v=o8MAFOFc7H0 This would allow to listen to the events "ItemListed", "ItemCanceled", and "ItemBought" from the NftMarketplace smart contract. The remaining missing elements to connect the dots with your course requirements now appears to be related to:

PatrickAlphaC commented 1 year ago

Thank you!

Yep... Trying to get to this this week, thanks!

BTT21000 commented 1 year ago

Great thank you! That Moralis forum thread may also assist even though the cloud functions aspect do not seem resolved. https://forum.moralis.io/t/streams-api-for-events-with-self-hosted-server/20758/16

PatrickAlphaC commented 1 year ago

Hmm... there are a lot of extra steps I'll need to add to do this self-hosted service... It sort of defeats the purpose of why I wanted to work with moralis in the first place.

What are your thoughts on me having users skip the moralis server part and just going straight to the graph? This isn't a small change... it's quite the overhaul.

PatrickAlphaC commented 1 year ago

I've made a poll here: https://github.com/smartcontractkit/full-blockchain-solidity-course-js/discussions/3806

I'm leaning to having users skip the Moralis server part. I've received a lot of feedback it's the most frustrating part of the course.

BTT21000 commented 1 year ago

Thanks for running the poll Patrick! I understand the logic of skipping directly to the Graph and agree with it. However since some of us have started with the Moralis section, I believe it'd be beneficial to at least have an idea of how to fix it with Moralis v2. This does not necessarily require a full video tutorial which would be very time consuming but maybe just a post listing the key bullet points of how to fix for self hosted Moralis v2. Or event better, some alternative Github repos patch to make it work with self hosted server. Btw it's probably something that could be delivered in collaboration with the Moralis team who could benefit from driving this for the community. So far my understanding of the key steps are:

PatrickAlphaC commented 1 year ago

Thanks for the insight! I think all the extra work it takes to get this repo "to fit" with the new moralis stuff isn't really worth it... I mean, it is if you want to but like... I created the project like this to make it easier but now it's just like... a lot harder.

I think I'm going to put a note to "follow along" but say "the moralis section has been updated, don't code with me for this one as it won't work correctly. " And mention the specific things I'd like them to learn.

Ahmeddh commented 1 year ago

Thanks @PatrickAlphaC and @BTT21000 for the insights, its been a frustrating experience with moralis to say the least, the docs are inconsistent and it seems they are used to making breaking changes without proper documentation.

That being said I'm proud I managed to make the Moralis self hosting works with the Moralis stream and parse, and got the ItemListed event successfully logged on a mongoDb database, it gave me a lot of confidence reaching this point almost without being spoon feed like in the course, but now I'm here it doesn't worth it as Patric said

Following on @BTT21000 thoughts ......

One thing about self-hosting it doesn't work with devChain, so you will have to first deploy your contracts to a testnet, I used Goerli

After you have your Moralis self-hosting working using parse instead of frpc in the course, you will now create a Moralis stream programmatically by customizing the addEvents.js as in the code below

const Moralis = require("moralis").default

const { EvmChain } = require("@moralisweb3/common-evm-utils")
require("dotenv").config()

const contractAddresses = require("./constants/networkMapping.json")
let chainId = process.env.CHAIN_ID || 5
const address = contractAddresses[chainId]["NftMarketplace"][0]
const itemListedAbi = [
    {
        anonymous: false,
        inputs: [
            {
                indexed: true,
                internalType: "address",
                name: "seller",
                type: "address",
            },
            {
                indexed: true,
                internalType: "address",
                name: "nftAddress",
                type: "address",
            },
            {
                indexed: true,
                internalType: "uint256",
                name: "tokenId",
                type: "uint256",
            },
            {
                indexed: false,
                internalType: "uint256",
                name: "price",
                type: "uint256",
            },
        ],
        name: "ItemListed",
        type: "event",
    },
] // valid abi of the event

const itemBoughtAbi = [
    {
        anonymous: false,
        inputs: [
            {
                indexed: true,
                internalType: "address",
                name: "buyer",
                type: "address",
            },
            {
                indexed: true,
                internalType: "address",
                name: "nftAddress",
                type: "address",
            },
            {
                indexed: true,
                internalType: "uint256",
                name: "tokenId",
                type: "uint256",
            },
            {
                indexed: false,
                internalType: "uint256",
                name: "price",
                type: "uint256",
            },
        ],
        name: "ItemBought",
        type: "event",
    },
]

const listingCancelledAbi = [
    {
        anonymous: false,
        inputs: [
            {
                indexed: true,
                internalType: "address",
                name: "nftAddress",
                type: "address",
            },
            {
                indexed: true,
                internalType: "uint256",
                name: "tokenId",
                type: "uint256",
            },
            {
                indexed: true,
                internalType: "address",
                name: "spender",
                type: "address",
            },
        ],
        name: "ListingCancelled",
        type: "event",
    },
]

const listingUpdatedAbi = [
    {
        anonymous: false,
        inputs: [
            {
                indexed: true,
                internalType: "address",
                name: "nftAddress",
                type: "address",
            },
            {
                indexed: true,
                internalType: "uint256",
                name: "tokenId",
                type: "uint256",
            },
            {
                indexed: true,
                internalType: "address",
                name: "spender",
                type: "address",
            },
            {
                indexed: false,
                internalType: "uint256",
                name: "oldPrice",
                type: "uint256",
            },
            {
                indexed: false,
                internalType: "uint256",
                name: "updatedPrice",
                type: "uint256",
            },
        ],
        name: "ListingUpdated",
        type: "event",
    },
]

async function main() {
    await Moralis.start({
        apiKey: process.env.NEXT_PUBLIC_API_KEY,
    })
    //ItemListed
    await startStream(
        "Monitor ItemListed",
        "ItemListed",
        "ItemListed(address,address,uint256,uint256)",
        itemListedAbi
    )

    //ItemBought
    await startStream(
        "Monitor ItemBought",
        "ItemBought",
        "ItemBought(address,address,uint256,uint256)",
        itemBoughtAbi
    )

    //ListingUpdated
    await startStream(
        "Monitor ListingUpdated",
        "ListingUpdated",
        "ListingUpdated(address,uint256,address,uint256,uint256)",
        listingUpdatedAbi
    )

    //ListingCancelled
    await startStream(
        "Monitor ListingCancelled",
        "ListingCancelled",
        "ListingCancelled(address,uint256,address)",
        listingCancelledAbi
    )
}

async function startStream(_desc, _tag, _topic, _abi) {
    const options = {
        chains: [EvmChain.GOERLI], // list of blockchains to monitor
        description: _desc, // your description
        tag: _tag, // give it a tag
        includeContractLogs: true,
        webhookUrl: process.env.NEXT_PUBLIC_WEB_HOOK_URL, // webhook url to receive events,
        abi: _abi,
        topic0: _topic,
        advancedOptions: [
            {
                topic0: _topic,
            },
        ],
    }

    const newStream = await Moralis.Streams.add(options)
    const { id } = newStream.toJSON() // { id: 'YOUR_STREAM_ID', ...newStream }

    // Now we attach bobs address to the stream

    await Moralis.Streams.addAddress({ address, id })
    console.log(`Stream created for ${_desc}`)
}

To test this you can run the mint-and-list.js script we made on the NftMarketplace smartcontract and you should see the item listed event in your MongoDb as in the screenshot here

Screen Shot 2022-12-01 at 12 08 55 AM

I will give it another 2 days to try and finish the marketplace with the self hosting and see if I can make it work, don't want to waste more than that in Moralis but its exciting to unstuck yourself (after 2 week of being just there)

PatrickAlphaC commented 1 year ago

I'd move forward off the Moralis stuff sadly :/

ri-dev-git commented 1 year ago

hey @Ahmeddh! I had a query, does the stream create another document for the events other than ItemlistedLogs or does it append it in the same document! Thank you for clarifying the process i was stuck on it for quite a while!

Ahmeddh commented 1 year ago

@ri-dev-git you will have to create a stream for each event as in the code in my previous reply