home Tutorial Cryptocurrency Transaction API with Node.js and Express

Cryptocurrency Transaction API with Node.js and Express

In the world of cryptocurrencies, accessing detailed transaction information is crucial for both developers and users. Whether you’re tracking the movement of funds, auditing transactions, or building applications on top of blockchain data, having a reliable way to fetch transaction details is essential. In this blog, we’ll walk you through building a Cryptocurrency Transaction Details API with Node.js and Express. This API fetches transaction details for various cryptocurrencies like Bitcoin, Ethereum, Dogecoin, Solana, and XRP.

Setting Up the Environment

Before we dive into the code, let’s set up our development environment. Ensure you have Node.js and npm installed on your machine. If not, you can download and install them from nodejs.org. Once installed, create a new project directory and initialize it:

mkdir crypto-details-api 
cd crypto-details-api 
npm init -y

Installing Dependencies

We need several npm packages to build our API. Here’s a list of dependencies and their purposes:

  • express: A minimal and flexible Node.js web application framework.
  • body-parser: Middleware to parse incoming request bodies.
  • dotenv: Loads environment variables from a .env file.
  • swagger-jsdoc and swagger-ui-express: Tools for generating and serving API documentation.
  • web3: A library to interact with Ethereum nodes.
  • axios: A promise-based HTTP client for the browser and Node.js.

Install these packages using the following command:

npm install express body-parser dotenv swagger-jsdoc swagger-ui-express web3 axios

Creating the Express Server

With our dependencies installed, let’s set up a basic Express server. Create a file named server.js and add the following code:

require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const swaggerJsDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');

const { getBitcoinDetails } = require('./bitcoinDetails.js'); // Importing the Bitcoin function
const { getDogecoinDetails } = require('./dogecoinDetails.js'); // Importing the Dogecoin function
const { getEthereumDetails } = require('./ethereumDetails.js'); // Importing the Ethereum function
const { getSolanaDetails } = require('./solanaDetails.js'); // Importing the Solana function
const { getXrpDetails } = require('./xrpDetails.js'); // Importing the XRP function

const app = express();
const port = 3000;

app.use(bodyParser.json());

// Swagger configuration
const swaggerOptions = {
    swaggerDefinition: {
        openapi: '3.0.0',
        info: {
            title: 'Crypto Details API',
            version: '1.0.0',
            description: 'API to fetch details of various cryptocurrencies',
            contact: {
                name: 'Your Name'
            },
            servers: [{ url: `http://localhost:${port}` }]
        },
    },
    apis: [__filename], // Path to the API docs
};

const swaggerDocs = swaggerJsDoc(swaggerOptions);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));

/**
 * @swagger
 * /getCryptoDetails:
 *   post:
 *     summary: Get details of a cryptocurrency
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               crypto:
 *                 type: string
 *                 example: 'bitcoin'
 *               address:
 *                 type: string
 *                 example: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'
 *     responses:
 *       200:
 *         description: Success
 *       400:
 *         description: Bad request
 */

app.post('/getCryptoDetails', async (req, res) => {
    const { crypto, address } = req.body;

    if (!crypto || !address) {
        return res.status(400).json({ error: 'Please provide a cryptocurrency and address' });
    }

    let details;
    switch (crypto.toLowerCase()) {
        case 'bitcoin':
            details = await getBitcoinDetails(address);
            break;
        case 'dogecoin':
            details = await getDogecoinDetails(address);
            break;
        case 'ethereum':
            details = await getEthereumDetails(address);
            break;
        case 'solana':
            details = await getSolanaDetails(address);
            break;
        case 'xrp':
            details = await getXrpDetails(address);
            break;
        default:
            return res.status(400).json({ error: 'Unsupported cryptocurrency' });
    }

    return res.json(details);
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

Integrating Swagger for API Documentation

Swagger is a powerful tool for documenting your APIs. It provides an interactive UI where you can test your API endpoints directly. In our server.js, we set up Swagger using swagger-jsdoc and swagger-ui-express. Here’s a brief explanation of the setup:

  • Swagger Definition: This includes metadata about your API like title, version, and description.
  • APIs Path: This points to the file(s) containing your API endpoints. Swagger will read the JSDoc comments and generate the documentation.

To access the Swagger documentation, start your server and navigate to http://localhost:3000/api-docs.

Fetching Cryptocurrency Details

Each cryptocurrency has a dedicated file for fetching transaction details. Let’s go through the Ethereum example in ethereumDetails.js:

const { Web3 } = require('web3');
const axios = require('axios');

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

async function getFirstTransactionHash(address) {
    try {
        const response = await axios.post(alchemyUrl, {
            jsonrpc: "2.0",
            method: "alchemy_getAssetTransfers",
            params: [{
                fromBlock: "0x0",
                toBlock: "latest",
                toAddress: address,
                category: ["external", "erc20", "erc721", "erc1155"],
                maxCount: "0x1"  // Specify maxCount in hex format
            }],
            id: 1
        });

        const transfers = response.data.result.transfers;
        if (!transfers || transfers.length === 0) {
            console.log('No transactions found for this address.');
            return null;
        }

        return transfers[0].hash;
    } catch (error) {
        console.error('Error fetching transaction hash:', error);
        return null;
    }
}

async function getTransactionDetails(transactionHash) {
    try {
        const transaction = await web3.eth.getTransaction(transactionHash);

        if (!transaction) {
            console.log('Unable to fetch the transaction.');
            return;
        }

        const gasFee = transaction.gas * transaction.gasPrice;
        return {
            sender: transaction.from,
            amountTransferred: web3.utils.fromWei(transaction.value, 'ether'),
            gasFee: web3.utils.fromWei(gasFee.toString(), 'ether'),
            txHash: transaction.hash
        };
    } catch (error) {
        console.error('Error fetching the transaction:', error);
        return null;
    }
}

async function getEthereumDetails(address) {
    const transactionHash = await getFirstTransactionHash(address);
    if (transactionHash) {
        return await getTransactionDetails(transactionHash);
    }
    return { error: 'No transactions found for this address.' };
}

module.exports = { getEthereumDetails };

Explanation

  • Web3 Initialization: We use Web3.js to interact with the Ethereum blockchain. The alchemyUrl is an environment variable that holds the Alchemy API endpoint.
  • getFirstTransactionHash: This function fetches the first transaction hash for a given address using the Alchemy API.
  • getTransactionDetails: This function fetches details of a transaction using the transaction hash.
  • getEthereumDetails: This function combines the previous two functions to fetch and return the transaction details for a given address.

Handling Different Cryptocurrencies

The logic for fetching transaction details is similar across different cryptocurrencies. Each file follows this pattern:

  1. Fetch the first transaction hash for the given address.
  2. Retrieve detailed information about the transaction.
  3. Extract and format the required details (sender’s address, amount transferred, gas fees).

Running the Server

To start the server, use the following command:

node server.js

Once the server is running, you can test the API using tools like Postman or by visiting the Swagger UI at http://localhost:3000/api-docs.

Testing the API

You can test the /getCryptoDetails endpoint by sending a POST request with the following JSON body:

{
  "crypto": "ethereum",
  "address": "your_ethereum_address"
}

Replace your_ethereum_address with an actual Ethereum address. The response will contain the transaction details for that address.

Conclusion

By following this guide, you’ve built a robust API that fetches transaction details for various cryptocurrencies. This API can serve as a foundation for more complex applications, such as wallets, transaction explorers, or financial analysis tools. The code is modular, making it easy to extend and maintain. Happy coding!

Future Enhancements

  • Add More Cryptocurrencies: Extend the API to support more cryptocurrencies.
  • Enhanced Error Handling: Implement more comprehensive error handling.
  • Caching: Add caching to improve performance for frequently requested addresses.
  • Security: Ensure that sensitive data, such as API keys, are securely managed.

Get Involved!

Dive into the world of cryptocurrency and API development with Techbreeze by building this project yourself! Explore the complete codebase, contribute, or simply learn from our resources. Visit the GitHub repository for all the details, and feel free to join our community of contributors!

 

 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.