After an event emits from my smart contract and I hear it server-side, I want to call a certain function in the smart contract and pass it some information to use.

I'm wondering how you place a transaction server-side. In this question it seems simple: Signing a transaction server-side

but how does the server-side know which account to use/private key. Browser-side it pops-up metamask and the user physically signs it. How does server-side do that? There is nobody to physically sign it and no where for it to pop-up?

Thanks for any help!

4 Answers 4


In order to sign a transaction for a certain account, you just need access to the private key for that account.

Plugins like MetaMask simply manage access to your private keys, and lets the user decide when and how they use their private key to sign transactions or messages.

For a server side application, you would need to store a private key that the service can use, and through your code, control when and where that service signs transactions.

Take a look at functions under web3.eth.accounts like:

It probably makes sense for you to generate a specific Ethereum account for your service, and let that service have special access to your contract if you expect there to be a high trust between these two applications. This is very similar to privileged service to service calls in modern application development.

  • Ah ok. So I'd put the private key into a variable and use it to 'unlock' the certain ethereum account I own. Cool thanks for the clarification. One question: how would I enable special access to my contract for a certain account. Do you mean something like require('thatAccountAddress' == msg.sender) so only that account can call the function? Or is their another pattern that can be used? Thanks!
    – savard
    Commented Aug 24, 2018 at 18:22
  • 1
    You would want to do some RBAC within your contract similar to Open-Zeppelin's Ownable.sol, basically where you define a certain address to have access to functions which other accounts would not have access to. This may not be required in your scenario, but usually in systems where you have a backend and smart contract that you own interacting, you would want to treat that differently. I also recommend that you generate a new account for your backend, rather than using your personal account. Commented Aug 24, 2018 at 18:30

I have extracted below code from my node js script where i am trying to connect with smart contract and watching for event. It may help you to get some idea.

var express = require('express'); var app = express(); const Web3 = require('web3'); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));

web3.eth.defaultAccount = web3.eth.accounts[1];

var StudentContract = web3.eth.contract([YOUR_ABI]);

var Student = StudentContract.at('YOUR_CONTRACT_ADD');

app.post('/upload', function(req, res) {

    Student.createStudents(studentName,studentAccYear, hashCode, {gas: '195253'});

    var studentEvent = Student.studentInfo();
    studentEvent.watch(function(error, result){
    if (!error)
            } else {


app.listen('3000', function(){ console.log('running on 3000...'); });

  • I don't understand how this helps at all. You're just setting a defaultAccount based off of preset (injected) accounts.. Commented Mar 28, 2021 at 21:23

On the client side wallets such as Metamask keep your account details (including private key) so for smart contract transactions you are intimidated with a pop-up for signing a transaction (metamask asking for the usage of the private key)

On the server side, it is somewhat similar, the only thing you need to store is the private key of the account with which you need to transact or execute a smart contract. And after your API execution, you can see your funds getting auto-decremented from your Metamask wallet in lieu of gas fees if any.

Use ethers.js library for smart contract execution.

Example usage on server side :-

  const provider = new ethers.providers.JsonRpcProvider(
  const signer = new ethers.Wallet('privateKeyString', provider);
  const contract = new ethers.Contract('contractAddress', abi, signer);
  await contract.someContractFunction();

Consider this solidity smart contract let's call function store using etherjs from server side.

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.2 <0.9.0;

contract Storage {

    uint256 number;

    function store(uint256 num) public {
        number = num;

    function retrieve() public view returns (uint256){
        return number;

you can refer the following code for the server side of the application

const express = require('express');
const ethers = require('ethers');
const app = express();
// const CONTRACT_ADDRESS='contract_address'
//const ABI = process.env.ABI
//const PRIVATE_KEY = process.env.PRIVATE_KEY
//example1 of rpc_url if using ganache or other local node
//example2 of rpc_url
//const ALCHEMY_API_KEY = 'your project API KEY'
// const RPC_URL = `https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}`
const provider = new ethers.providers.JsonRpcProvider('Your_RPC_URL');
const signer = new ethers.Wallet('PRIVATE_KEY', provider);
const contractInstance = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer);

app.post('/store', async(req, res) => {
    try {
        const {number} = req.body;
        const tx = await contractInstance.store(number);
        await tx.wait();
        res.json({success: true})
    catch (error) {
app.get('/retrieve', async(req, res) => {   
    try {
        const number = await contractInstance.retrieve();
    catch (error) {
const port = 5000;
app.listen(port, () => {
    console.log("API server is listening on port 5000")

Note: Kindly keep your private key secure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.