Social media


How I created my own decentralized cryptocurrency and bank in less than 1 hour

Author: LB 2021-03-03 350

One of my recent aha moments in life was when I finally understood the main difference between bitcoin and ethereum. I was very much into cryptographic algorithms and I was looking at the algorithmical differences between the two cryptocurrencies. I read a lot about the SHA-256 hash function and the DAGs in ethereum, but a few days ago I finally decided to find out what the ethereum infrastructure has been invented for. The best way to learn something is to do it, so I started reading tutorials on how to create decentralised decentralized applications or dapps. Building my first decentralized bank and developing my first cryptocurrency on the ethereum testnet marks a pivotal milestone in my life, therefore I’d like to share the most important steps and talk a little bit about the difficulties I had to face during development.

Dapps interact with the ethereum blockchain via smart contracts. These contracts can be looked at as simple program codes that are executed as soon as a user is trying to perform some kind of operation that is in connection with the smart contract. I found one of the easiest tutorials on the web for smart contracts, which happened to be a very straightforward implementation of a cryptocurrency.

Cryptocurrencies are very similar to fiat currencies in a sense that they can be issued and users can transfer them between accounts. We don’t expect much more from these creatures and in order to implement such operations on the ethereum blockchain with a smart contract the following solidity code taken from the official site suffices:

pragma solidity ^0.5.0;
contract Coin {
    // The keyword "public" makes those variables
    // easily readable from outside.
    address public minter;
    mapping (address => uint) public balances;
    // Events allow light clients to react to
    // changes efficiently.
    event Sent(address from, address to, uint amount);
    // This is the constructor whose code is
    // run only when the contract is created.
    constructor() public {
     minter = msg.sender;
    }
    function mint(address receiver, uint amount) public {
    require(msg.sender == minter);
    require(amount < 1e60);
    balances[receiver] += amount;
    }
    function send(address receiver, uint amount) public {
     require(amount <= balances[msg.sender], "Insufficient balance.");
     balances[msg.sender] -= amount;
     balances[receiver] += amount;
     emit Sent(msg.sender, receiver, amount);
    }
   }


The code implements the necessary functionalities, such as “send” and “mint”. Now we need to deploy this smart contract onto the ethereum blockchain, but we don’t want to pay for transaction fees, every single time we access our smart contract. In this case, we can use a convenient ethereum testnet implementation with the following commands:


Download the ethereum testnet:


$ sudo npm install -g ganache-cli


Run the testnet:

$ ganache-cli

Once the testnet is up and running, you can deploy the smart contract from Remix to the testnet. You can achive that by clicking on "Deploy" in Remix. Don't forget to select Web3 Provider as an environment before you hit "Deploy".


And the next step was to install a nodejs binary on my system. I managed to do that by downloading the executable binary from the official NodeJs site. I had to implement a few endpoints in my NodeJs based web server to reply to the request comming from the GUI. I developed the following NodeJs code for this purpose:


const http = require('http');
var express = require('express');
var fs = require('fs');
const Web3 = require('web3');
let web3 = new Web3('ws://localhost:8545');
const hostname = '127.0.0.1';
const port = 3000;
web3.eth.getAccounts().then(console.log);
var app = express();
app.use(express.static('public'));
const MyContract = new web3.eth.Contract([{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Sent","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"send","outputs":[],"stateMutability":"nonpayable","type":"function"}],"0xEb1cE03a26617328d2D558f14C2b0b8CE7FCf621")
const server = http.createServer((req, res) => {
  if (req.url === '/send-money') {
  MyContract.methods.send("0x69402829B26DDC039B462AfB4bF7b42a4E0ed7DA",2).send({from: '0xe4DcFDEDFe2b631d6BC586B9e18737E7e6C868e3'})
  .then(function(result){
    console.log(result);
  });
      res.writeHead(200, {'Content-Type': 'text/html'});
      res.end();
  }
  if (req.url === '/mint-money1') {
  MyContract.methods.mint("0xe4DcFDEDFe2b631d6BC586B9e18737E7e6C868e3",2).send({from: '0x674A0964f6516e1ed2d048DfaE685dD834eD201B'})
  .then(function(result){
    console.log(result);
      res.writeHead(200, {'Content-Type': 'text/html'});
      res.end();
  });
  MyContract.methods.balances("0xe4DcFDEDFe2b631d6BC586B9e18737E7e6C868e3").call({from: '0xe4DcFDEDFe2b631d6BC586B9e18737E7e6C868e3'})
  .then(function(result){
    console.log(result);
  });
  }
  if (req.url === '/return-balance-1') {
  MyContract.methods.balances("0xe4DcFDEDFe2b631d6BC586B9e18737E7e6C868e3").call({from: '0xe4DcFDEDFe2b631d6BC586B9e18737E7e6C868e3'})
  .then(function(result){
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.write(result);
      res.end();
  });
  }
  if (req.url === '/return-balance-2') {
  MyContract.methods.balances("0x69402829B26DDC039B462AfB4bF7b42a4E0ed7DA").call({from: '0xe4DcFDEDFe2b631d6BC586B9e18737E7e6C868e3'})
  .then(function(result){
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.write(result);
      res.end();
  });
  }
  if (req.url === '/mint-money2') {
  MyContract.methods.mint("0x69402829B26DDC039B462AfB4bF7b42a4E0ed7DA",2).send({from: '0x674A0964f6516e1ed2d048DfaE685dD834eD201B'})
  .then(function(result){
    console.log(result);
      res.writeHead(200, {'Content-Type': 'text/html'});
      res.end();
  });
  MyContract.methods.balances("0x69402829B26DDC039B462AfB4bF7b42a4E0ed7DA").call({from: '0x674A0964f6516e1ed2d048DfaE685dD834eD201B'})
  .then(function(result){
    console.log(result);
  });
  }
  if (req.url === '/index') {
    fs.readFile('index.html',function (err, data){
      res.writeHead(200, {'Content-Type': 'text/html','Content-Length':data.length});
      res.write(data);
      res.end();
    });
}
    if(req.url.indexOf('bootstrap.min.css') != -1){ //req.url has the pathname, check if it conatins '.css'
      fs.readFile(__dirname + '/public/bootstrap.min.css', function (err, data) {
      if (err) console.log(err);
      res.writeHead(200, {'Content-Type': 'text/css'});
      res.write(data);
      res.end();
      });
    }
    if(req.url.indexOf('signin.css') != -1){ //req.url has the pathname, check if it conatins '.css'
      fs.readFile(__dirname + '/public/signin.css', function (err, data) {
      if (err) console.log(err);
      res.writeHead(200, {'Content-Type': 'text/css'});
      res.write(data);
      res.end();
      });
    }
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});


The most challening part was to obtain the contract's ABI representation, because I had to pass that as a parameter to the Contract's constructor. If you want to extract the ABI data from the contract itself, you have to convert the contract file using the following command:


$ solcjs test.sol --abi


If you don't have solcjs installed on your computer, you can have one installed by using the following command:


$ sudo npm install -g solc-js


Finally, I decided to create a nice HTML page for my new decentralized bank with a few buttons on it to mint my crytpocurrencies and enable the users to transfer these between their accounts:


<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <link rel="icon" href="/docs/4.0/assets/img/favicons/favicon.ico"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <title>Decentralised bank</title> <link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/sign-in/"> <!-- Bootstrap core CSS --> <link rel="stylesheet" type ="text/css" href="bootstrap.min.css" integrity="sha384- BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- Custom styles for this template --> <link href="signin.css" type ="text/css" rel="stylesheet"> <style> ul { list-style: none; } </style> </head> <body class="text-center"> <div> <h1 style="" class="">Decentralised bank</h1><br><br> <img style="float: right" src=" https://static8.depositphotos.com/1005404/996/i/600/depositphotos_9968183-stock-photo-build-bank.jpg"/> </div> <ul> <li> <h1 class="h3 mb-3 font-weight-normal">Crypto operations</h1><br><br></li> <li> <div></li> <li> <button type="button" class="btn btn-primary" onclick="send_to_peter()"> Mine and transfer to Peter</button><br></li> <li> <div id="mined1"></div><br></li> <li> <button onclick="send_to_anna()">Mine and transfer to Anna</button><br></li> <li> <div id="mined2"></div><br></li> <li> <button onclick="peter_send_to_anna()">Peter transfers 2 coins to Anna</button><br></li> <li> <div id="peter_send_to_anna"></div><br></li> <li> </div></li> <li> <h1 class="h3 mb-3 font-weight-normal">Account balances </h1><br></li> <li> <div></li> <li> <button type="button" class="btn btn-primary" onclick="get_peter_balance()">Retrive</button> Peter's balance: <span id="peter-balance"></span><br></li> <li> </div></li> <li> <div></li> <li> <button type="button" class="btn btn-primary" onclick="get_anna_balance()">Retrive</button> Anna's balance: <span id="anna-balance"></span><br></li> <li> </div></li> </ul> </body> <script> function send_to_peter(){ var jsondata = { "send_to_peter": 1 }; $.ajax({ url: "/mint-money1", method: "POST", data: JSON.stringify({ Data: jsondata }), contentType: "json", success: function(data){ document.getElementById("mined1").innerHTML = "<span style='color: green' >Minted and sent!</span>"; get_peter_balance(); }, error: function(errMsg) { document.getElementById("mined1").innerHTML = "<span style='color: red' >Problem...</span>"; } }); }; function peter_send_to_anna(){ var jsondata = { "peter_send_to_anna": 1 }; $.ajax({ url: "/send-money", method: "POST", data: JSON.stringify({ Data: jsondata }), contentType: "json", success: function(data){ document.getElementById("peter_send_to_anna").innerHTML = "<span style='color: green' >Sent!</span>"; get_peter_balance(); get_anna_balance(); }, error: function(errMsg) { document.getElementById("peter_send_to_anna").innerHTML = "<span style='color: red' >Problem...</span>"; } }); }; function send_to_anna(){ var jsondata = { "send_to_anna": 1 }; $.ajax({ url: "/mint-money2", method: "POST", data: JSON.stringify({ Data: jsondata }), contentType: "json", success: function(data){ document.getElementById("mined2").innerHTML = "<span style='color: green' >Minted and sent!</span>"; get_anna_balance(); }, error: function(errMsg) { document.getElementById("mined2").innerHTML = "<span style='color: red' >Problem...</span>"; } }); }; function get_peter_balance(){ var jsondata = { "send_to_peter": 1 }; $.ajax({ url: "/return-balance-1", method: "POST", data: JSON.stringify({ Data: jsondata }), contentType: "json", success: function(data){ document.getElementById("peter-balance").innerHTML = "<span style='color: green' >Balance: "+data+"</span>"; }, error: function(errMsg) { document.getElementById("peter-balance").innerHTML = "<span style='color: red' >Problem...</span>"; } }); }; function get_anna_balance(){ var jsondata = { "send_to_peter": 1 }; $.ajax({ url: "/return-balance-2", method: "POST", data: JSON.stringify({ Data: jsondata }), contentType: "json", success: function(data){ document.getElementById("anna-balance").innerHTML = "<span style='color: green' >Balance: "+data+"</span>"; }, error: function(errMsg) { document.getElementById("anna-balance").innerHTML = "<span style='color: red' >Problem...</span>"; } }); }; </script> </html>


It might not be straightforward to implement even with the source codes I shared with you in the sections above, but if you spend some time on it I'm pretty sure you can get your decentralized bank with your own cryptocurrency up and running. Feel free to modify the code as much as you wish!

Interesting entries


29.08.2021

Mining ravencoin and farming chia on the same machine

23.07.2021

What is my ROI on my chia farm investment?

06.05.2021

Russian miners are already testing the Nvidia CMP 30HX chip for mining

05.05.2021

Technical details and the ROI of Chia Network Farming

30.04.2021

Investigating monero mining on a notebook