[SOLVED] Query to Moralis DB not working on Vercel from Next.js API Routes

I have database queries setup in my Next.js API routes and it works fine on local dev environment but it does not return any results when uploaded to Vercel.

Should these queries be in cloud functions instead?

Localhost returns results for a specific endpoint. Production URL returns null. Both are calling the same database and same data so both should return the same.

// @route    POST api/v1/asset/:address/:tokenId/listing-status
// @desc     Get listing status (trade and sale) for token Id
// @access   Public
import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';

import * as Sentry from '@sentry/nextjs';
import Moralis from 'moralis-v1/node';

import { ALLOWED_ADDRESSES } from '@/lib/allowed-addresses/allowedAddress';

const serverUrl = process.env.NEXT_PUBLIC_MORALIS_SERVER_URL;
const appId = process.env.NEXT_PUBLIC_MORALIS_APP_ID;
const masterKey = process.env.masterKey;

const handler: NextApiHandler = async (req: NextApiRequest, res: NextApiResponse) => {
    const allowedMethods = ['GET'];

    if (!allowedMethods.includes(req.method!)) {
        return res.status(405).send({ message: 'Method not allowed.' });
    }

    if (req.method === 'GET') {
        await Moralis.start({
            serverUrl,
            masterKey,
            appId,
        });

        const { tokenId } = req.query as {
            tokenId: string;
        };

        if (!ALLOWED_ADDRESSES.includes(token_address)) {
            return res.status(405).send({ message: 'Address is not valid' });
        }

        try {
            // const currentUser = await Moralis.User.current();

            const PolygonItem = Moralis.Object.extend('PolygonItems');
            const query = new Moralis.Query(PolygonItem);
            query.select(
                'token_address',
                'token_id',
                'owner_of',
                'for_trade',
                'for_sale',
                'listing_price',
                'duration',
                'expiry',
                'sale_token',
                'order'
            );
            query.equalTo('token_address', token_address); 
            query.equalTo('token_id', tokenId);
            console.log(`PolygonItem LISTING STATUS | Query: ${JSON.stringify(query)}`);

            const item = await query.first({ useMasterKey: true });

            if (!item) {
                return res.status(200).json(null);
            }

            console.log(`PolygonItem LISTING STATUS | Results: ${JSON.stringify(item)}`);

            return res.status(200).json(item);
        } catch (err) {
            Sentry.captureException(err);
            console.error(err);

            return res.status(500).json({ message: `Error updating item trade status. ${err}` });
        }
    } else {
        res.send({
            message: "Something's not right. Check your API call. Note, this route only accepts post requests!",
        });
    }
};

export default handler;

const serverUrl = process.env.NEXT_PUBLIC_MORALIS_SERVER_URL;
const appId = process.env.NEXT_PUBLIC_MORALIS_APP_ID;
const masterKey = process.env.masterKey;

Have you set these environment variables in Vercel?

Have you whitelisted any domains for your Moralis server? Are you getting any errors in your browser console?

envโ€™s are fine and I redeployed to make sure. No whitelist and no browser errors.

I made a cloud function to try and it gets the params but doesnโ€™t find results when called via API route. It works if I call directly from Postman.

This is the logged results from calling the cloud function directly to ${serverUrl}/functions/getListingStatus?_ApplicationId=${appId}&token_address=${token_address}&tokenId=${tokenId} from within Vercel API route using Postman.

This returns blank results:

2022-11-02T22:00:39.750Z - PolygonItem LISTING STATUS | Results: undefined

2022-11-02T22:00:39.730Z - PolygonItem LISTING STATUS | Query: {"where":{"token_address":"0x67F473226....","token_id":"444818"},"keys":"token_address,token_id,owner_of,for_trade,for_sale,listing_price,duration,expiry,sale_token,order"}

2022-11-02T22:00:39.727Z - Logs...{"params":{"_ApplicationId":"6KIsWv6......","token_address":"0x67F47322......","tokenId":"444818"},"master":false,"log":{"options":{"jsonLogs":false,"logsFolder":"./logs","verbose":false,"maxLogFiles":1},"appId":"6KIsWv......"},"headers":{"connection":"Upgrade","host":"127.0.0.1:1337","accept-encoding":"gzip","x-forwarded-for":"18.118.149.96","cf-ray":"764024f01a95e1ef-YYZ","x-forwarded-proto":"https","cf-visitor":"{\"scheme\":\"https\"}","accept":"application/json","content-type":"application/json","user-agent":"node-fetch/1.0 (+https://github.com/bitinn/node-fetch)","sentry-trace":"3542f628b540405f8cafe0........","baggage":"sentry-environment=production,sentry-release=989637a5ba705......,sentry-transaction=GET%20%2Fapi%2Fv1%2Fasset%2F0x67f4732266.....%2F%5BtokenId%5D%2Flisting-status,sentry-public_key=f806d7dadc6e4......,sentry-trace_id=3542f628b5404....,sentry-sample_rate=1","cf-connecting-ip":"18.118.149.96","cf-ipcountry":"US","cdn-loop":"cloudflare"},"ip":"18.118.149.96","functionName":"getListingStatus","context":{}}

GET request directly to ${serverUrl}/functions/getListingStatus?_ApplicationId=${appId}&token_address=${token_address}&tokenId=${tokenId} using Postman

This returns a result:

2022-11-02T21:53:52.316Z - PolygonItem LISTING STATUS | Results: {"token_address":"0x67f47322.....","token_id":"444818","owner_of":"0x0abc....","for_trade":true,"for_sale":true,"listing_price":0.1,"duration":"3","expiry":"2022-11-05T19:09:24.753Z","sale_token":"0x7ceB2.....","createdAt":"2022-11-02T18:26:27.454Z","updatedAt":"2022-11-02T19:30:49.994Z","order":{"__type":"Pointer","className":"OrdersDirectV4","objectId":"5fYh2u...."},"objectId":"9NrxDttnSa6bhOVXKfd1KdA1"}

2022-11-02T21:53:52.287Z - PolygonItem LISTING STATUS | Query: {"where":{"token_address":"0x67f473226.","token_id":"444818"},"keys":"token_address,token_id,owner_of,for_trade,for_sale,listing_price,duration,expiry,sale_token,order"}

2022-11-02T21:53:52.284Z - Logs...{"params":{"_ApplicationId":"6KIsWv6F.","token_address":"0x67f4......","tokenId":"444818"},"master":false,"log":{"options":{"jsonLogs":false,"logsFolder":"./logs","verbose":false,"maxLogFiles":1},"appId":"6KIsWv......"},"headers":{"connection":"Upgrade","host":"127.0.0.1:1337","accept-encoding":"gzip","x-forwarded-for":"174.88.241.68","cf-ray":"76401afd2c6ea204-YYZ","x-forwarded-proto":"https","cf-visitor":"{\"scheme\":\"https\"}","user-agent":"PostmanRuntime/7.29.2","accept":"*/*","postman-token":"f2c7a643-416d......","cf-connecting-ip":"174.88.241.68","cf-ipcountry":"CA","cdn-loop":"cloudflare"},"ip":"174.88.241.68","functionName":"getListingStatus","context":{}}

What is your Moralis server URL and your Vercel deployment URL? You can direct message if you donโ€™t want to share them publicly.

Got it working. The collection address I was querying had capital letters in Vercel and everywhere else I was using it was lowercase.

I think I remember seeing somewhere that all addresses should be converted to lowercase for cloud functions?

You can handle that in your route handler if needed, but checksum versions of addresses (that has capitals) should still work normally with the Moralis API.

1 Like