visit
First, we can run the command node --version
in our terminal to ensure NodeJS and NPM are on our machine.
npm install -g truffle ganache
Checking the version number for Truffle and Ganache with truffle --version
and ganache --version
respectively will tell us if both tools were installed successfully.
The next step is to , then navigate to the Extensions tab in the editor and search for Truffle for VS Code.
With the Truffle for VS Code extension, we can easily create a new Truffle project through the VS Code command palette. Press ctrl + shift + P
in the editor to open up the command palette and type truffle
to see a list of commands we can use. Select Truffle: New Solidity Project and then create basic project to create a new project in the desired folder.
The ability to use console.log
in our smart contract code is another great new feature . Before we create the smart contract for our project, let’s set that up by installing the required package. Navigate to the project folder in the terminal and type the following command:
npm install @ganache/console.log
In the contracts folder, create a new file and call it SimpleContract.sol. Next, fill it with the following smart contract code:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import '@ganache/console.log/console.sol';
contract SimpleContract {
constructor() {
console.log('\n\n#################################################\n'
'#### Now Deploying Contract ####\n'
'#################################################'
);
}
function donate() public payable {
console.log('Successfully Donated ', msg.value);
}
function getBalance() public view returns (uint256) {
console.log("This contract's balance is:", address(this).balance);
return address(this).balance;
}
// Needed in order to receive payments
receive() external payable {}
}
The code in our smart contract is relatively simple. It displays a message in the console when we deploy our smart contract, provides the functionality to donate ETH and query the balance, and prints messages in the console when calling the functions.
After installing the Truffle for VS Code Extension, we can easily deploy by right-clicking the smart contract file and choosing Deploy Contracts. However, if we want to see our console messages, we will have to use our own terminal rather than the one built into VS Code. This could potentially change in the future, but for now, we will have to create a simple migration script to carry out the deployment.
In the migrations folder, create a new script called 1_SimpleContract.js
and input the following code:
const SimpleContract = artifacts.require("SimpleContract");
module.exports = function (deployer) {
deployer.deploy(SimpleContract);
};
Next, open up a new terminal window and start Ganache:
ganache
This terminal window is where we will see our console messages when they appear. We now have two terminal windows open: one running Ganache and the other open in the folder of our Truffle project.
truffle migrate --network development
If the deployment is successful, we can see our console message printed in the terminal:
Great! Our contract is live on our local Ganache instance! We’ll leave Ganache running for now so we can interact with our contract using the browser. Before we get to that, copy the contract address
from the output in the terminal where we typed the migrate
command. We will use this address to point our frontend to our smart contract.
npx create-react-app ganache-browser-test
Next, we will install Web3.JS to easily interact with our smart contract. Navigate into our new project folder and install Web3.JS with this command:
cd ganache-browser-test
npm install web3
Newer versions of create-react-app don’t play nicely with Web3.JS, so we need to install a specific version of React Scripts. We can do so with this command:
npm install --save-exact [email protected]
Finally, to use Ganache in our browser, we will install it directly as a dependency:
npm install ganache
Alternatively, you can add the CDN link in the html to access Ganache from the browser:
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/web/ganache.min.js"></script>
Before we start working on the frontend code, we need to create a file containing our contract’s ABI so that we can interact with our smart contract. We can copy that file directly from our Truffle project. Navigate to the build/contracts folder in our Truffle project and copy the SimpleContract.json file.
Next, open up our frontend project in the editor and create a new folder called abi. In that folder, paste the SimpleContract.json file. The file structure for our frontend now looks like this:
With all the setup out of the way, we can start working on our frontend. First, open the App.js file in the src folder and replace the boilerplate code with this:
import { useState } from 'react';
import './App.css';
import SimpleContract from './abi/SimpleContract.json';
const ganache = require('ganache');
const Web3 = require('web3');
const options = {}
const provider = ganache.provider(options);
const web3 = new Web3('//127.0.0.1:8545');
const CONTRACT_ADDRESS = 'YOUR_CONTRACT_ADDRESS'
const USER_ADDRESS = web3.utils.toChecksumAddress('YOUR_ACCOUNT_ADDRESS');
const contractInstance = new web3.eth.Contract(SimpleContract.abi, CONTRACT_ADDRESS);
const App = () => {
const [contractBalance, setContractBalance] = useState(0);
const donate = async () => {
const donationAmount = document.querySelector('#donationAmount').value;
const response = await contractInstance.methods.donate().send({
from: USER_ADDRESS,
value: web3.utils.toWei(donationAmount)
});
console.log('donate response:', response);
};
const getBalance = async () => {
const response = await contractInstance.methods.getBalance().call();
console.log('getBalance response:', response);
setContractBalance(web3.utils.fromWei(response));
}
return (
<div className="App">
<header className="App-header">
<h1>Ganache In The Browser</h1>
<div>
<input
type='number'
id='donationAmount'
defaultValue={0.01}
/>
<label htmlFor='donationAmount'>ETH</label>
<br></br>
<button
id='donate'
type='button'
onClick={donate}
>
Donate
</button>
</div>
<div>
<button
id='getBalance'
type='button'
onClick={getBalance}
>
Get Contract Balance
</button>
</div>
<div>
<p>
{contractBalance} ETH
</p>
</div>
</header>
</div>
);
}
export default App;
Be sure to change CONTRACT_ADDRESS
to the address we received when deploying our smart contract back in Step 4. As well, the USER_ADDRESS
is the account that will call the functions. We can get this from the list of accounts that displays when we first started our Ganache instance in the terminal:
SimpleContract
JSON file.ganache
and Web3
variables.options
variable that we initialize our provider
instance with.
options
variable is where we would set we would like our local blockchain instance to include, such as forking Mainnet or Goerli, when running Ganache strictly in the browser (without it running in our other terminal window).web3
object using our localhost URL
and port 8545
, where our Ganache instance is already running.
provider
variable instead of localhost. We are using localhost
in this case since we want to interact with our already deployed smart contract and see our console.log
messages in the terminal output.CONTRACT_ADDRESS
and USER_ADDRESS
variables.App
code.contractBalance
React state variable and its set
method.donate
and getBalance
functions.html
for our frontend.Now we can run our app with npm start
to display our frontend, which looks like this:
When we test our project, we can see the results and our console.log
messages displayed on the terminal window which is running Ganache, and the ETH balance on our frontend successfully updates with the new balance.
const options = { fork: { network: 'goerli' } };
Or:
const options = { fork: { network: 'mainnet' } };
Then we need to update our web3
variable declaration:
const web3 = new Web3(options);
Finally, we need to make sure that we update CONTRACT_ADDRESS
with our address on whichever network we are forking. We also need to update USER_ADDRESS
to an account address on the same network that has sufficient funds to donate to our contract.
const options = { fork: { network: 'mainnet' } };
const provider = ganache.provider(options);
const web3 = new Web3(provider);
const CONTRACT_ADDRESS = '0x692586eaC70114C8F4714D89E7f72FAAbaeE0Cd7'
const USER_ADDRESS = web3.utils.toChecksumAddress('0xCe7A99Bba7018fa455E6eD5CF88a7F26010F1E8F');
And with that, we could test our project with a forked version of mainnet using Ganache in our browser.