QuickNode: Create a Token dApp using QuickNode
Learn how to create a Token dApp using QuickNode.
QuickNode is a platform that allows you to deploy dApps and other applications onto over 12 different blockchain networks with immediate provisioning and availability. QuickNode offers a variety of powerful tools and analytics, all presented through a single control panel dashboard.
This tool is available on a Linux or macOS system.
Set up a credentials file for S3FS at
${HOME}/.passwd-s3fs
. You will need to save your Filebase Access and Secret keys to this file and give it owner permissions. You can do so with the following commands:echo ACCESS_KEY_ID:SECRET_ACCESS_KEY > ${HOME}/.passwd-s3fs
chmod 600 ${HOME}/.passwd-s3fs
ACCESS_KEY_ID is your Filebase Access key, and SECRET_ACCESS_KEY is your Filebase Secret key. For more information on Filebase access keys, see here.
You can mount a Filebase IPFS bucket with the command:
s3fs mybucket /path/to/mountpoint -o passwd_file=${HOME}/.passwd-s3fs -o url=https://s3.filebase.com
- mybucket: name of your Filebase bucket
- /path/to/mountpoint
Create a react projet for your app:
npx create-react-app my-dapp
This will create a new project directory called
my-dapp
. Navigate into this directory with the command:cd my-dapp
Before we can install Hardhat, we’ll need to remove the default ‘README.md’ file, since it’ll cause a conflict during the Hardhat initialization. Use the following command to remove this file:
rm README.md
npm install --save-dev "[email protected]^2.9.3" "@nomiclabs/[email protected]^2.0.0" "[email protected]^3.0.0" "[email protected]^4.2.0" "@nomiclabs/[email protected]^2.0.0" "[email protected]^5.0.0"
npx hardhat
Select ‘Create a Basic Sample Project’ > ‘Create a Basic Project’, then select the current directory as the project root, and select ‘Y’ to include a .gitignore.

This command created some project files, such as the contracts and scripts directories.


This tutorial does not use any add-ons. Then select ‘Continue’.



Remove the default file called
Greeter.sol
, then create a new file called dApp.sol
.Enter the following content in this new file:
//dApp.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
contract Token {
string public name = "dApp token";
string public symbol = "DAT";
// The fixed amount of tokens stored in an unsigned integer type variable.
uint256 public totalSupply = 1000000;
// An address type variable is used to store ethereum accounts.
address public owner;
// A mapping is a key/value map. Here we store each account balance.
mapping(address => uint256) balances;
/**
* Contract initialization.
*
* The `constructor` is executed only once when the contract is created.
* The `public` modifier makes a function callable from outside the contract.
*/
constructor() {
// The totalSupply is assigned to transaction sender, which is the account
// that is deploying the contract.
balances[msg.sender] = totalSupply;
owner = msg.sender;
}
/**
* A function to transfer tokens.
*
* The `external` modifier makes a function *only* callable from outside
* the contract.
*/
function transfer(address to, uint256 amount) external {
// Check if the transaction sender has enough tokens.
// If `require`'s first argument evaluates to `false` then the
// transaction will revert.
require(balances[msg.sender] >= amount, "Not enough tokens");
// Transfer the amount.
balances[msg.sender] -= amount;
balances[to] += amount;
}
/**
* Read only function to retrieve the token balance of a given account.
*
* The `view` modifier indicates that it doesn't modify the contract's
* state, which allows us to call it without executing a transaction.
*/
function balanceOf(address account) external view returns (uint256) {
return balances[account];
}
}
This contract creates a custom token that we’ll use for your dApp later. Replace the token’s public name and public symbol with whatever you’d like.
To do this, we’ll deploy it on a local HardHat node. To get a list of the local, fake accounts created by HardHat, run the command:
npx hardhat node
Your console output will look like this:

From here, we can see we have 20 test accounts to use.
require("@nomiclabs/hardhat-ethers");
​
module.exports = {
defaultNetwork: "rinkeby",
networks: {
rinkeby: {
url: "QUICKNODE_API_URL",
accounts: "WALLET_PRIVATE_KEY"
}
},
solidity: {
version: "0.7.0",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
paths: {
sources: "./contracts",
tests: "./test",
cache: "./cache",
artifacts: "./artifacts"
},
mocha: {
timeout: 20000
}
}
Replace the following values:
- QUICKNODE_API_URL: Your QuickNode endpoint URL
- WALLET_PRIVATE_KEY: Your crypto wallet private key
//deploy.js
const hre = require("hardhat");
async function main() {
// ethers is avaialble in the global scope
const [deployer] = await hre.ethers.getSigners();
console.log(
"Deploying the contracts with the account:",
await deployer.getAddress()
);
​
console.log("Account balance:", (await deployer.getBalance()).toString());
​
const Token = await hre.ethers.getContractFactory("Token");
const token = await Token.deploy();
await token.deployed();
​
console.log("Token address:", token.address);
​
}
​
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
First, make sure your cryptowallet is configured to use the Rinkeby network. If you’re using Metamask, follow the instructions found here.

Once the transaction is complete, you should have 0.1ETH to use:

npx hardhat run –network rinkeby scripts/deploy.js

Take note of this token address.

The Token Symbol should auto-populate after adding the contract address. Scroll down to ‘Token Decimal’. In this tutorial, our contract uses a decimal of 0.



npx start

import './App.css';
import {ethers} from 'ethers'
import { useState } from 'react';
import TokenArtifact from "./artifacts/contracts/dApp.sol/Token.json"
const tokenAddress = "CONTRACT_ADDRESS"
​
function App() {
const [tokenData, setTokenData] = useState({})
const [amount, setAmount] = useState()
const [userAccountId, setUserAccountId] = useState()
​
async function requestAccount() {
await window.ethereum.request({ method: 'eth_requestAccounts' });
}
​
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
async function _intializeContract(init) {
// We first initialize ethers by creating a provider using window.ethereum
// When, we initialize the contract using that provider and the token's
// artifact. You can do this same thing with your contracts.
const contract = new ethers.Contract(
tokenAddress,
TokenArtifact.abi,
init
);
​
return contract
}
async function _getTokenData() {
const contract = await _intializeContract(signer)
const name = await contract.name();
const symbol = await contract.symbol();
const tokenData = {name, symbol}
setTokenData(tokenData);
}
async function senddAppToken() {
if (typeof window.ethereum !== 'undefined') {
await requestAccount()
const contract = await _intializeContract(signer)
const transaction = await contract.transfer(userAccountId, amount);
await transaction.wait();
console.log(`${amount} dAppToken has been sent to ${userAccountId}`);
}
}
async function getBalance() {
if (typeof window.ethereum !== 'undefined') {
const contract = await _intializeContract(signer)
const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' })
const balance = await contract.balanceOf(account);
console.log("Account Balance: ", balance.toString());
}
}
return (
<div className="App">
<header className="App-header">
<button onClick={_getTokenData}>get token data</button>
<h1>{tokenData.name}</h1>
<h1>{tokenData.symbol}</h1>
<button onClick={getBalance}>Get Balance</button>
<button onClick={senddAppToken}>Send dAppToken</button>
<input onChange={e => setUserAccountId(e.target.value)} placeholder="Account ID" />
<input onChange={e => setAmount(e.target.value)} placeholder="Amount" />
</header>
</div>
);
}
export default App;
Replace ‘CONTRACT_ADDRESS’ with your Token’s contract address from step 19. Once saved, will look like this:

Using this app, you’ll be able to get the current wallet balance of dApp token in our wallet, send dApp Tokens to other wallets such as the test wallets we got the addresses of earlier, and get dApp token data.
This react front-end of our app can be customized to your liking and can include other scripts, functions, or even images and animations.
If you have any questions, please join our Discord server, or send us an email at [email protected]​
Last modified 8mo ago