Making a URL shortener on Ethereum Blockchain ⛓


The Product

πŸ”— https://t.co/Rte4yKrN1q shutting down is old news. But have you found a replacement? Well, we did! A link shortener that will keep your link stored for a lifetime ... because it's on the blockchain. Check out @sauravtom's Ethereum URL shortener at https://t.co/QhsWph5eOi!

β€Šβ€”β€Š@makersup

How it works

The web app deployed at 0x.now.sh , interacts with a smart contract deployed on Ethereum Ropsten testnet . Being on testnet means you can interact with it using free ethers. Get your free ethers here .

0x.now.sh

Ethereum Ropsten testnet

free ethers here

The Process

The SmartContract πŸ“ƒοƒ

pragma solidity ^0.4.24;
contract e0x {
 event LinkVisited(string url, uint linkId);
 event LinkAdded(uint linkId, string url);

 struct LinkTemplate {
  address userAddress;
  string url;
 }

 uint lastLinkId;
 mapping (uint => LinkTemplate) public linkMapping;

 constructor() public {
  lastLinkId = 0;
 }


 function createNewLink(string url) public returns (uint) {
     lastLinkId++;
  linkMapping[lastLinkId] = LinkTemplate(msg.sender, url);
  emit LinkAdded(lastLinkId, url);
  return lastLinkId;
 }

 modifier linkExists(uint linkId) {
     //link with the given hash does not exist
  if(linkMapping[linkId].userAddress == 0x0000000000000000000000000000000000000000) {
   revert();
  }
  _;
 }

 function getLink(uint linkId) linkExists(linkId) public constant
  returns(
   address,
   string
  ) {
      //emit LinkVisited(linkId, link.url);
      LinkTemplate memory link = linkMapping[linkId];
   return(
      link.userAddress,
      link.url
   );
  }
event LinkAdded(uint linkId, string url);

 struct LinkTemplate {
  address userAddress;
  string url;
 }

 uint lastLinkId;
 mapping (uint => LinkTemplate) public linkMapping;

 constructor() public {
  lastLinkId = 0;
 }


 function createNewLink(string url) public returns (uint) {
     lastLinkId++;
  linkMapping[lastLinkId] = LinkTemplate(msg.sender, url);
  emit LinkAdded(lastLinkId, url);
  return lastLinkId;
 }

 modifier linkExists(uint linkId) {
     //link with the given hash does not exist
  if(linkMapping[linkId].userAddress == 0x0000000000000000000000000000000000000000) {
   revert();
  }
  _;
 }

 function getLink(uint linkId) linkExists(linkId) public constant
  returns(
   address,
   string
  ) {
      //emit LinkVisited(link.url,linkId);
      LinkTemplate memory link = linkMapping[linkId];
   return(
       link.userAddress,
       link.url
   );
  }

Technical Challenges

Making the shortened URLs accessible in all Browsers

This was quite tricky because interacting with blockchain required the browser to be web3 enabled, and have some wallet installed (metamask or similar). Currently web3 and wallet support is only for Chrome and Firefox on Desktop only. To solve this, I had to create a wallet on the fly as follows

provider = ethers.getDefaultProvider('ropsten');
wallet = ethers.Wallet.createRandom();
wallet = wallet.connect(provider);

Shout out to ethersJS library for having support for this.

ethersJS library

Counting URL visits

The flexibility for using this one all browsers comes at a cost. Each time user clicks on the shortened URL no change is made to the blockchain state, hence it is not possible to determine how many times each link was clicked. This issues remains unsolved. The complete source code for this project is on Github .

Github Pull Requests welcome 😁