Yes, you have some alternatives, we can write the API that will serve as a layer between our frontend application and our smart contract, currently there are a subscription method to do that with web3.js
.
But remember that you need a web-socket endpoint to use subscriptions in web3.js
Inside your project folder, create files routes.js
, server.js
, and config.js
.
server.js is the main file that runs as Node.js server. We are requiring all of the dependencies at the beginning of the file, using cors and Express, we can check for Web3.js and make it interact with blockchain network by providing a localhost address.
const express = require('express');
const app = express();
const cors = require('cors');
const routes = require('./routes');
const Web3 = require('web3');
const mongodb = require('mongodb').MongoClient;
const contract = require('@truffle/contract');
const artifacts = require('./build/contracts/Contacts.json');
const CONTACT_ABI = require('./config');
const CONTACT_ADDRESS = require('./config');
app.use(cors());
app.use(express.json());
if (typeof web3 !== 'undefined') {
var web3 = new Web3(web3.currentProvider);
} else {
This is an example connecting to a MongoDB ready to use in the future, so inside the callback function of the mongodb.connect(), we connect with Cluster0 and getting accounts from the Ethereum blockchain network.
Using the 'web3 Contract function', open the config.js file where we pass CONTACT_ABI and CONTACT_ADDRESS we have connected with the smart contract.
const CONTACT_ADDRESS = '0xB7fC6C3DFebD24EAe16E307Ea39EdF7c93ff7866';
const CONTACT_ABI = [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "contacts",
"outputs": [
{
"internalType": "uint256",
"name": "id",
"type": "uint256"
},
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "phone",
"type": "string"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [],
"name": "count",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "string",
"name": "_phone",
"type": "string"
}
],
"name": "createContact",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
];
module.exports = {
CONTACT_ABI,
CONTACT_ADDRESS,
};
Then we will call routes() with all the parameters, creating this routes function in routes.js to listen the app on 'port 3000'.
function routes(app, db, accounts, contactList) {
app.get('/contacts', async (request, response) => {
let cache = [];
const COUNTER = await contactList.methods.count().call();
for (let i = 1; i <= COUNTER; i++) {
const contact = await contactList.methods.contacts(i).call();
cache = [...cache, contact];
}
response.json(cache);
});
}
module.exports = routes
We loop through all the COUNTER and get contacts one-by-one from contactList, which we place in the cache
variable and finally send to the frontend in response.
Run the server which is now ready to receive requests from React app.
$ nodemon server.js
You can find more based in the web3.eth.contract official documentation and web3.eth.accounts, including this related post using 'Chainlink' or Polygon as another option.