Skip to main content

Node.js 20 Runtime

Updated on
Jun 25, 2024

Overview

The Node.js v20 Runtime enables you to build and deploy serverless functions using the Node.js v20 environment. This runtime provides access to Node.js core modules and allows you to include additional npm packages by uploading a zip file containing your function code and dependencies.

Available Packages

The Node.js v20 runtime includes the following core modules:


  • assert
  • buffer
  • child_process
  • cluster
  • console
  • crypto
  • dgram
  • dns
  • events
  • fs
  • http
  • https
  • net
  • os
  • path
  • process
  • querystring
  • readline
  • stream
  • string_decoder
  • tls
  • tty
  • url
  • util
  • v8
  • vm
  • zlib

For more details, you can refer to the Node.js GitHub repository.

Using the Code Editor

Within the code editor, you can write and test your function using the core modules listed above. Here is a simple example of a Node.js function:


function main(params) {
// Extract dataset and network from metadata in params
const dataset = params.metadata.dataset;
const network = params.metadata.network;

return {
message: `This is data from the ${dataset} dataset on the ${network} network.`,
params
};
}

Uploading a Zip File

If you need to include additional npm packages, you can upload your function as a zip file. Follow these steps:


  • Step 1: Create your function code in index.js.
  • Step 2: Create a package.json file with your dependencies.
  • Step 3: Run npm install to install the dependencies.
  • Step 4: Zip the contents of your project directory, including index.js, package.json, and the node_modules directory. Note: Make sure that you do not zip the containing folder. Instead, select the files you want to include in your zip, for example the index.js, .env, and package.json files as well as the node_modules directory, and compress them into an archive.
  • Step 5: Upload the zip file in the function editor.
  • Step 6: Test the function with the Block with Receipts dataset on Ethereum Mainnet.

Example package.json:


{
"name": "qn-token-metadata-parser",
"version": "1.0.0",
"description": "A boilerplate to process Ethereum block and receipt data for erc-20 and erc-721 transfer events",
"main": "index.js",
"dependencies": {
"axios": "^0.27.2",
"dotenv": "^16.4.5",
"web3": "^1.10.4"
}
}

Example index.js:


require('dotenv').config();
const Web3 = require('web3');
const axios = require('axios');
const https = require('https');

const web3 = new Web3(new Web3.providers.HttpProvider(process.env.QUICKNODE_URL));

// Create an HTTPS Agent that specifies the TLS protocol
const httpsAgent = new https.Agent({
secureProtocol: 'TLSv1_2_method' // Using TLS 1.2 as an example; adjust as necessary based on the server's requirements
});

async function getTokenMetadata(contractAddress) {
console.log(`Fetching token metadata for address: ${contractAddress}`); // Log the address being queried
try {
const response = await axios.post(process.env.QUICKNODE_URL, {
id: 67,
jsonrpc: "2.0",
method: "qn_getTokenMetadataByContractAddress",
params: [{
contract: contractAddress
}]
}, {
headers: {
'Content-Type': 'application/json'
},
httpsAgent: httpsAgent // Use the custom HTTPS Agent
});
console.log('Response data:', response.data); // Log response data
return response.data.result;
} catch (error) {
console.error('Error fetching token metadata:', error); // Log errors if the request fails
throw error; // Rethrow error to handle it upstream if necessary
}
}

async function parseLogs(logs) {
const summaries = [];
console.log(`Parsing logs: ${logs.length} entries found`); // Log number of logs to be parsed

for (const log of logs) {
console.log(`Processing log entry:`, log); // Log each log entry
if (log.topics[0] === '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef') {
const from = '0x' + log.topics[1].slice(26);
const to = '0x' + log.topics[2].slice(26);
if (log.topics.length === 4) {
// ERC-721 Transfer event
const tokenId = Web3.utils.hexToNumberString(log.topics[3]);
summaries.push(`Transaction ${log.transactionHash} - Transferred NFT token ID ${tokenId} from ${from} to ${to}`);
} else {
// ERC-20 Transfer event
const metadata = await getTokenMetadata(log.address);
const value = Web3.utils.fromWei(log.data, 'ether');
const readableValue = (parseInt(value) / Math.pow(10, metadata.decimals)).toFixed(metadata.decimals);
summaries.push(`Transaction ${log.transactionHash} - Transferred ${readableValue} ${metadata.symbol} (${metadata.name}) from ${from} to ${to}`);
}
}
}
console.log('Completed parsing logs:', summaries); // Log summaries of all parsed logs
return summaries;
}

async function main(params) {
console.log('Starting main function with params:', params); // Log input params
try {
const { data } = params;
const results = await Promise.all(data.map(async entry => {
const { block, receipts } = entry;
console.log(`Processing block number ${block.number} with receipts`); // Log details of the block being processed
return {
blockNumber: block.number,
transactions: await Promise.all(receipts.map(async receipt => ({
transactionHash: receipt.transactionHash,
logsSummary: await parseLogs(receipt.logs)
})))
};
}));
console.log('Final results:', results); // Log final results
return { results };
} catch (error) {
console.error('Error in main function:', error); // Log any errors encountered in the main function
throw error;
}
}

module.exports = { main };

Example .env:

# QUICKNODE_URL = https://your-quicknode-url
# If you don't have a QuickNode Endpoint, you can get one here: https://dashboard.quicknode.com/endpoints

QUICKNODE_URL="YOUR_QUICKNODE_URL"
Share this doc