The Chainlink Hardhat Starter Kit Now Supports TypeScript
We’re excited to announce a new version of our most popular developer starter kit: the Chainlink Hardhat Starter Kit now supports Typescript! Keep reading for a breakdown of all of the new features.
A Refresher—The Chainlink Hardhat Starter Kit
Hardhat is a JavaScript- and TypeScript-based development environment that enables developers to compile, deploy, test, and debug EVM-compatible smart contracts. A year ago, we released the Chainlink Hardhat Starter Kit, a single repo with everything developers need to start building with Chainlink, including smart contracts, tests, advanced tasks, and deployment scripts. You can read more about it on our blog.
One year later, this project comes with a brand new Typescript version. To use the initial JavaScript version, open your terminal and enter
git clone https://github.com/smartcontractkit/hardhat-starter-kit.git
To switch to the TypeScript version, you need to checkout to the typescript
branch.
git checkout typescript
What’s Inside?
TypeScript
TypeScript is an object-oriented coding language, a superset of JavaScript developed to overcome code complexity for large projects. This means that all TypeScript code is valid JavaScript code, but not the other way around. One of the key advantages of TypeScript is that it is strongly typed, which means that the compiler alerts users of any type-related errors, which results in early bug detection. Code written in TypeScript is better structured and more concise than JavaScript code.
Tests
Testing has truly been leveled up with this new edition. Test files are divided into two separate categories—unit tests and staging tests. Each test listens for a specific event when waiting for a callback from the oracle network.
Each unit test is independent and callback responses from the oracle network are mocked using a wide pallet of test contracts and helpers from the official Chainlink repository. This means you can save time by running them in parallel using the following command:
yarn test --parallel
Staging tests, on the other hand, use already deployed instances of contracts on various test networks while listening for the events. There are no mocked contracts or simulated callbacks. You can speed Hardhat up by preventing ts-node from recompiling and type-checking your project on every run by setting the TS_NODE_TRANSPILE_ONLY
env variable to 1.
Additionally, in tests, you can fork mainnet in a concrete block by uncommenting the “forking” property in a Hardhat config file and setting “enabled” to true. You will need an archival node or JSON RPC provider like Alchemy for this.
TypeChain
TypeChain generates TypeScript typings (d.ts) files for your Solidity smart contracts. With JavaScript, you need to remember not only the name of a given smart contract method or event but also its full signature. This wastes time and might introduce bugs that will be triggered only in runtime. TypeChain enabled more precise and efficient tests, tasks, and scripts.
NatSpec
Ethereum Natural Language Specification Format, or NatSpec for short, is a form for comments meant to provide rich documentation to Solidity smart contracts. These comments use tags such as @notice
, @params
, @return
, etc., and can be used to describe pretty much anything from contracts themselves to functions, including variables, events, or even modifiers. But not just that, the messages generated by NatSpec are directly meant to be displayed to the end-users when they are interacting with your contract functions, i.e., signing a transaction.
Code Coverage
In smart contract development, understanding code coverage is an underrated skill, especially if you practice test-driven development. It is a measure in percent of the degree to which the smart contract source code is executed when a particular test suite is run. A project with high test coverage has a lower chance of containing undetected bugs compared to a project with low test coverage. To develop secure dApps, you should reach at least 90 percent of code coverage. However, don’t try to chase 100 percent coverage at all costs because this can result in unexpected side effects.
To run it, enter:
yarn coverage
Some Solidity files, like mock contracts whose only purpose is to serve as test helpers, will display low coverage percentages. To exclude them from checks, update the “.solcover.js” file.
Estimating Gas
Programming smart contracts for EVM-compatible chains means programming with limited resources. For this reason, developers tend to optimize their code as much as possible. Gas optimizations can be tricky, a Mocha reporter has been added to the test suites that displays gas usage per unit test and various metrics for method calls and deployments.
To estimate gas, just set a REPORT_GAS
environment variable to true, and then run:
yarn hardhat test
The output will be stored in a “gas-report.txt” file. If you’d like to see the gas prices in USD or another currency, add a COINMARKETCAP_API_KEY
from Coinmarketcap.
View Contracts Size
Ever spent weeks building a smart contract only to encounter the “max code size exceeded” error during the deployment process? This means that you hit the smart contract code size limit (24,576 bytes for Ethereum testnets) and that you’ll need to reduce the size of the contract before deploying, or split it into several smaller contracts and libraries. To avoid massive refactoring at the end of the development process, a simple command to display the size of each smart contract in the project has been added so you can be aware of this limitation way earlier and act accordingly.
To view contract size, run:
yarn run hardhat size-contracts
Fuzz Testing
Due to the immutable nature of smart contracts, you always want to be sure to test every possible scenario before deployment on the blockchain. That’s why the TypeScript edition of the Chainlink Hardhat Starter Kit comes with a fuzzer to find edge cases that couldn’t be found using the unit or staging tests. Fuzz testing is a technique that generates a massive number of random scenarios to uncover values that produce unexpected results.
Echidna has been included as a fuzz testing tool in this starter kit. You need to have Docker installed with at least 8GB of virtual memory allocated. To update this parameter go to Settings -> Resources -> Advanced -> Memory.
You can also run Echidna from the source. For more information, visit the Echidna public repository.
To start the Echidna instance, run the following command from the project root directory
yarn fuzzing
If you are using it for the first time, you will need to wait for Docker to download the eth-security-toolbox image. This may take a while. The previous command will copy the content of the project directory into the “/src” directory inside the Docker container.
Fuzz testing has only been implemented for the Automation-compatible smart contract example, but feel free to experiment with it and add more. The main focus of this test is to implement the fuzzing of block timestamps. The idea is that, no matter what, the performUpkeep
function can’t update the counter
state variable before the set interval of time.
To start fuzzing, run
echidna-test /src/contracts/test/fuzzing/KeepersCounterEchidnaTest.sol --contract KeepersCounterEchidnaTest --config /src/contracts/test/fuzzing/config.yaml
After a couple of minutes you will see the test results in the console. To exit Echidna, type
exit
VRF v2
The final addition is, of course, the new version of Chainlink Verifiable Random Function! Chainlink VRF v2 includes several improvements to the way you fund and request randomness for your smart contracts. You’ll find a complete walkthrough of how to write VRF v2 compatible contracts, how to deploy them, how subscription management works, and how to properly test and use them.
To start, navigate to the VRF Subscription Page, select network, connect your wallet, and click “Create subscription”. Then save your “subscriptionId” as the VRF_SUBSCRIPTION_ID
environment variable. After deployment, head back to the VRF subscription page, navigate to your subscription, click the “Add consumer” button, and paste the address of the recently deployed VRF consumer contract. Once that’s done, you can perform a VRF request with the request-random-number
task:
yarn hardhat request-random-number --contract insert-contract-address-here --network network
Once you have successfully made a request for a random number, you can see the result via the read-random-number
task:
yarn hardhat read-random-number --contract insert-contract-address-here --network network
If you encounter an error, check on the VRF subscription page to see if the request has been fulfilled and try again.
Summary
TypeScript is understandably a popular choice for the development of large or complex applications, whereas JavaScript is often preferred for smaller projects. Head to the Chainlink public repository and start experimenting with this and the other starter kits available.
Learn more about Chainlink by visiting chain.link or reading the documentation at docs.chain.link. To discuss an integration, reach out to an expert.