paint-brush
Create a Crypto Crowdfunding Widget From a Few Lines of Codeby@thebojda
375 reads
375 reads

Create a Crypto Crowdfunding Widget From a Few Lines of Code

by Laszlo FazekasDecember 3rd, 2021
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Would you like to start your very own crowdfunding campaign? Or collect some money for fixing a Github issue? Or would you accept some donations for your article? It’s super easy with crypto. In this article, we will build a crypto crowdfunding widget for accepting ERC-20 tokens or crypto on any Ethereum compatible network.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - Create a Crypto Crowdfunding Widget From a Few Lines of Code
Laszlo Fazekas HackerNoon profile picture


Would you like to start your very own crowdfunding campaign? Or collect some money for fixing a Github issue? Or would you accept some donations for your article? It’s super easy with crypto. In this article, we will build a crypto crowdfunding widget for accepting ERC-20 tokens or crypto on any Ethereum compatible network.


The Theory

Our widget will be a dynamically generated PNG that is generated from our Ethereum address and balance. You can embed this image anywhere where you can embed images by URL. You can add it to your GitHub readme or into the description of an issue, or you can embed it into your article, etc. The image will contain a QR code to your Ethereum address and an indicator that shows your balance, and how far is it from the target. When you start a new campaign, you have to create a new Ethereum account or a smart contract (ex.: an ICO contract) to accept the funds.


The user can simply scan the QR code and send some crypto. It takes about 10 seconds. Sending crypto to a crowdfunding campaign has never been easier.


The Code

We’ll use JavaScript for the implementation and node-canvas for generating the resulting PNG image.


First of all, we’ll create a gray canvas.


const canvas = createCanvas(200, 270)
const ctx = canvas.getContext('2d')
ctx.fillStyle = "#aaaaaa"
ctx.fillRect(0, 0, canvas.width, canvas.height)


Then paint the QR code onto it. We’ll use the qrcode library for this.


let qrcode = new Image()
qrcode.src = await QRCode.toDataURL(config.ETH_ADDRESS)
ctx.drawImage(qrcode, 10, 10, 180, 180)


The next step is querying the balance. We can easily do it by using the web3 library.


const web3 = new Web3(config.PROVIDER_URL)
const balance = parseInt(await web3.eth.getBalance(config.ETH_ADDRESS))


The constructor of the Web3 class has a provider parameter. This is the URL of the Ethereum JSON-RPC endpoint. If you would use the Ethereum Mainnet, or one of the test networks then the best way is to use ConsenSys’s Infura. MetaMask also uses this. If you want to accept payments on an alternative Ethereum compatible network like Polygon, or xDAI, etc. then you can find RPC endpoints here.


It is also possible to query your ERC20 balance if you want to accept token payments.


const contract = new web3.eth.Contract(erc20_abi as AbiItem[], CONTRACT_ADDRESS)
const balance = await contract.methods.balanceOf(config.ETH_ADDRESS).call()


The constructor of the Contract class has 2 parameters the interface definition (ABI) and the address of the ERC20 token contract.


If the balance is known, calculating the percent is very easy.


let percent = balance / (config.TARGET_VALUE * 10 ** 18);
if (percent > 1)
    percent = 1;


It’s important that the balance is in wei so you have to divide it by 10^18.


The full code looks like this:


const web3 = new Web3(config.PROVIDER_URL)
const balance = parseInt(await web3.eth.getBalance(config.ETH_ADDRESS))

const canvas = createCanvas(200, 270)
const ctx = canvas.getContext('2d')
ctx.fillStyle = "#aaaaaa"
ctx.fillRect(0, 0, canvas.width, canvas.height)

let qrcode = new Image()
qrcode.src = await QRCode.toDataURL(config.ETH_ADDRESS)
ctx.drawImage(qrcode, 10, 10, 180, 180)

ctx.fillStyle = '#000000'
ctx.font = '12px Impact'
ctx.fillText(config.TEXT, 10, 210)
ctx.fillText(`${(balance / 10 ** 18).toFixed(2).toString()} ${config.SYMBOL} / ${config.TARGET_VALUE.toFixed(2).toString()} ${config.SYMBOL}`, 10, 230)

ctx.fillStyle = '#ffffff'
ctx.fillRect(10, 240, 180, 10)

let percent = balance / (config.TARGET_VALUE * 10 ** 18);
if (percent > 1)
    percent = 1;

ctx.fillStyle = '#037362'
ctx.fillRect(10, 240, Math.round(180 * percent), 10)

ctx.strokeStyle = '#000000'
ctx.lineWidth = 1
ctx.strokeRect(10, 240, 180, 10)


23 lines of code. As I wrote, it’s not a big deal. The full code is available on GitHub. (And I also have a PHP implementation.)


The code can run on a minimal Lightsail instance (3,5$/mo), but if you don’t want to allocate a full EC2 instance to it, you can deploy it to AWS lambda. Everything is included in the GitHub repo.


It’s a sample widget that collects xDAI (and by the way, if you like the article, or simply want to try how it works, you can send me some xDAI):


Crowdfunding Widget


Happy coding...