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.
Being a Decentralized application means that this web app does not require any centralized database to function. It only interacts with the smart contract deployed on the blockchain.
pragma solidity ^0.4.24;
contract e0x {event Log(string message);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 existif(linkMapping[linkId].userAddress == 0x0000000000000000000000000000000000000000) {revert();}_;}
function getLink(uint linkId) linkExists(linkId) public constantreturns(address,string) {LinkTemplate memory link = linkMapping[linkId];return(link.userAddress,link.url);}
}
EthersJS library is used to talk to the blockchain
// provider picks up the Metamask injected web3 object from browserlet provider = new ethers.providers.Web3Provider(web3.currentProvider);let address = "ADDRESS_OF_DEPLOYED_SMART_CONTRACT";let abi = [...] //defines JSON interface for the smart contract
// calling the createNewLink function defined in the smart contracttx = await contract.createNewLink(url);console.log(tx.hash);
contract.on("LinkAdded", (linkId, linkUrl) => {
var shortUrl = '{0}/s?id={1}'.f(window.location.origin, linkId.toNumber())
$("#info").prepend( "Short URL: <a href='{0}'>{0}</a><br>".f(shortUrl) );
});
web3’s allEvents() function call was used to list down all the events recorded in the smart contract whenever a new url was shortened.
MyContract = web3.eth.contract(abi);myContractInstance = MyContract.at(address);events = myContractInstance.allEvents({event: 'LinkAdded', fromBlock: 0, toBlock: 'latest'});events.watch(function(error, result){console.log(result.args.url, result.args.linkId.toNumber());...});
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 the awesome ethersJS library for having support for this.
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.
Pull Requests welcome 😁