Skip to content

Commit

Permalink
Merge pull request #74 from jim380/ethereum
Browse files Browse the repository at this point in the history
ethereum Txs
  • Loading branch information
uwezukwechibuzor authored Oct 2, 2023
2 parents e5b9bab + 27d81ca commit 9fc7802
Show file tree
Hide file tree
Showing 10 changed files with 2,714 additions and 20 deletions.
8 changes: 6 additions & 2 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ FROM node:16.2.0-alpine
RUN mkdir -p /usr/app/
WORKDIR /usr/app

#copy fro to
# Copy your project files to the container
COPY ./ ./

RUN npm install --force
# Install build tools and Python
RUN apk add --no-cache make gcc g++ python2

# Install Node.js dependencies
RUN npm install --force
28 changes: 28 additions & 0 deletions backend/Model/ethereum/Model.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const mongoose = require("mongoose");

const TxsSchema = new mongoose.Schema({
blockNumber: {
type: Number,
required: true,
unique: false,
},
hash: {
type: String,
required: true,
unique: true,
},
timestamp: Number,
transactionIndex: Number,
from: String,
to: String,
value: String,
nonce: Number

});

//set bitcoin chain schema
const ethereumTransactions = mongoose.model("ethereum-Transactions", TxsSchema);

module.exports = {
ethereumTxsModel: ethereumTransactions,
};
23 changes: 23 additions & 0 deletions backend/Routes/Chains/ethereum/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const express = require("express");
const app = express();
const corsMiddleware = require("../../../corsMiddleware.js");
const { createEthereumCronJob } = require("../../../cron.js");
const Model = require("../../../Model/ethereum/Model.jsx");
const ethereumTxsHandler = require("../../../data/chainQueries/ethereum/handlers.js");

//cron task for Bitcoin
createEthereumCronJob();

// Define a helper function to prefix the routes with "/ethereum"
function ethereumRoute(routePrefix, path, handler) {
return app.get(`/${routePrefix}${path}`, corsMiddleware, handler);
}

// Define the routes
const ethereumRoutes = (routePrefix, txsModel) => {
ethereumRoute(routePrefix, "/txs", ethereumTxsHandler(txsModel));
};

ethereumRoutes("ethereum", Model.ethereumTxsModel);

module.exports = app;
13 changes: 13 additions & 0 deletions backend/cron.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const cron = require("node-cron");
require("dotenv").config();
const fetchLatestBlocksAndTxs = require("./data/chainQueries/cosmos/latestBlocksAndTxs.js");
const fetchBitcoinTxs = require("./data/chainQueries/bitcoin/index.js");
const fetchEthereumTxs = require("./data/chainQueries/ethereum/index.js");

//cron to run at every 3sec to get latest blocks
function createCronJob(options) {
Expand All @@ -27,7 +28,19 @@ function createBitcoinCronJob(apiUrl, txsModel) {
});
}

// ethereum cron job
function createEthereumCronJob() {
return cron.schedule("*/5 * * * * *", async () => {
try {
await fetchEthereumTxs();
} catch (error) {
console.error("Error", error);
}
});
}

module.exports = {
createCronJob,
createBitcoinCronJob,
createEthereumCronJob,
};
12 changes: 12 additions & 0 deletions backend/data/chainQueries/ethereum/handlers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { getAllTxs } = require("../../dbQueries");

const ethereumTxsHandler = (txModel) => async (req, res) => {
try {
const data = await getAllTxs(req, res, txModel);
res.json(data);
} catch (error) {
res.status(500).json({ error: error.message });
}
};

module.exports = ethereumTxsHandler;
85 changes: 85 additions & 0 deletions backend/data/chainQueries/ethereum/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const { Network, Alchemy } = require("alchemy-sdk");
const { Web3 } = require("web3");
const Model = require("../../../Model/ethereum/Model.jsx");

// Initialize a Web3 instance (connect to an Ethereum node if needed)
const web3 = new Web3();

const settings = {
apiKey: "iHiSvMYKjRZEuwF_ma9IecHZUjiHiagG",
network: Network.ETH_MAINNET,
};

const alchemy = new Alchemy(settings);

async function fetchEthereumTxs() {
try {
// Retry logic for network errors
const retryCount = 3;
let attempt = 0;
let block;

while (attempt < retryCount) {
attempt++;

try {
// Get the latest block
block = await alchemy.core.getBlock("latest");
break;
} catch (networkError) {
console.error(
`Network error (attempt ${attempt}):`,
networkError.message
);

// Add delay before retrying (you can adjust the delay duration)
await new Promise((resolve) => setTimeout(resolve, 5000));
}
}

if (!block) {
console.error(
"Failed to retrieve the latest block after multiple attempts."
);
return;
}

// Create an array to store transaction data objects
const transactionsDataArray = [];

// Fetch transaction details for each transaction in the block
for (const txHash of block.transactions) {
const tx = await alchemy.core.getTransaction(txHash);
const value = web3.utils.hexToNumberString(tx.value._hex);
// convert value to ethers
const convertValue = value / 10 ** 18;

// Create a new transaction data object and push it to the array
const transactionsData = new Model.ethereumTxsModel({
blockNumber: tx.blockNumber,
hash: tx.hash,
timestamp: block.timestamp,
transactionIndex: tx.transactionIndex,
from: tx.from,
to: tx.to,
value: convertValue,
nonce: tx.nonce,
});

transactionsDataArray.push(transactionsData);
}

// Insert all transaction data objects in a single batch
await Model.ethereumTxsModel.insertMany(transactionsDataArray);
} catch (error) {
if (error.code === 11000) {
// Duplicate key error, you can log it and continue
return;
} else {
// Handle other errors
console.error("Error:", error);
}
}
}

module.exports = fetchEthereumTxs;
Loading

0 comments on commit 9fc7802

Please sign in to comment.