A Node.js backend built with TypeScript and Express, designed to interact with an ERC20 token smart contract using the viem library. This project lets you deploy a token, interact with it (balance, approve, transfer, transferFrom), and test blockchain logic locally using Hardhat.
- Node.js v22
- Yarn or npm
- TypeScript installed globally or via
ts-node
npm install
# or
yarn installnpm run start:nodeThis will start a local Ethereum network at http://127.0.0.1:8545 and give you test accounts with private keys.
From the Hardhat node logs, choose an account's private key and paste it into your .env file:
DEFAULT_ACCOUNT_PRIVATE_KEY=0x...
npm run compile:contractnpm run deploy:contractAfter deployment, copy the deployed contract address from the terminal output and paste it into .env:
CONTRACT_ADDRESS=0xYourDeployedContractAddress
npm run start:serverYour backend will run at: http://localhost:3000
# Blockchain
RPC_URL=http://127.0.0.1:8545
DEFAULT_ACCOUNT_PRIVATE_KEY=0x...
# Contract
CONTRACT_ADDRESS=0x...
CONTRACT_INFO_PATH=artifacts/contracts/Token.sol/CustomToken.json
# Server
PORT=3000
NODE_ENV=development| Command | Description |
|---|---|
| start:node | Starts a local Hardhat blockchain |
| compile:contract | Compiles the Solidity smart contract |
| deploy:contract | Deploys the contract using TypeScript/viem |
| start:server | Starts the Express backend server |
| test | Runs backend tests (Jest) |
Execute a token transfer on behalf of another address.
- URL: http://127.0.0.1:3000/api/transferFrom
- Method: POST
- Headers: Content-Type: application/json
{
"from": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"amount": 100
}{
"success": true,
"hash": "0x...",
"from": "0x7099...",
"to": "0xf39f...",
"amount": "100",
"message": "Transferred 100 tokens from 0x7099... to 0xf39f..."
}Make sure that from has already approved the DEFAULT_ACCOUNT_PRIVATE_KEY to spend tokens on its behalf.
- Viem over Ethers.js: We chose viem for modern type-safety, performance, and better developer ergonomics.
- Modular Architecture: Routes, blockchain logic, and deployment scripts are separated for maintainability.
- Manual ABI Injection: The ABI is pulled dynamically from artifacts/ after compilation to avoid redundancy.
- TypeScript: Strong typing across the project for safer contract interaction and better DX.
- Middleware: Includes custom error handling and JSON parsing.