Use Truffle with Dijets Utility Chain
Introduction#
Truffle Suite is a toolkit for launching decentralized applications (dapps) on the EVM. With Truffle you can write and compile smart contracts, build artifacts, run migrations and interact with deployed contracts. This tutorial illustrates how Truffle can be used with Dijets's Utility Chain, which is an instance of the EVM.
Recommended Knowledge#
- Completed the tutorial Run a Dijets Node.
- You are familiar with Dijets Smart Contract Guide Repo.
- Basic understanding of the Dijets's architecture.
- Understand the purpose and how to complete an IntraChain swap in Dijets.
Dependencies#
- Dijets-Up is a tool for running a local Dijets network. It's similar to Truffle's Ganache.
- NodeJS v8.9.4 or later.
- Truffle, which you can install with
npm install -g truffle
Start up a Local Dijets Network#
Dijets-Up allows you to spin up a private test network deployments.
To start a local five nodes Dijets network run:
_10cd /path/to/dijets-up_10# start a five node staking network_10./go run examples/local/fivenodenetwork/main.go
A five node Dijets network is running on your machine. Network will run until you Ctrl + C to exit.
Create Truffle Directory and Install Dependencies#
Open a new terminal tab to so we can create a truffle
directory and install some further dependencies.
First, navigate to the directory within which you intend to create your truffle
working directory:
_10cd /path/to/directory
Create and enter a new directory named truffle
:
_10mkdir truffle; cd truffle
Use npm
to install web3, which is a library
through which we can talk to the EVM and
DijetsJS which is used for cross chain
swaps.
_10npm install web3 dijets -s
We'll use web3 to set an HTTP Provider which is how web3 will speak to the EVM. Lastly, create a boilerplate truffle project by initialising it with:
_10truffle init
The local development network pre-funds some static addresses when created. We'll use @truffle/hdwallet-provider to use these pre-funded addresses as our accounts.
_10npm install @truffle/hdwallet-provider
Update truffle-config.js#
One of the files created when you ran truffle init
is truffle-config.js
. Add the following to truffle-config.js
.
_35const Web3 = require("web3")_35const HDWalletProvider = require("@truffle/hdwallet-provider")_35_35const protocol = "http"_35const ip = "localhost"_35const port = 9650_35Web3.providers.HttpProvider.prototype.sendAsync =_35 Web3.providers.HttpProvider.prototype.send_35const provider = new Web3.providers.HttpProvider(_35 `${protocol}://${ip}:${port}/ext/bc/C/rpc`_35)_35_35const privateKeys = [_35 "0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027",_35 "0xbbc2865b76ba28016bc2255c7504d000e046ae01934b04c694592a6276988630",_35 "0xcdbfd34f687ced8c6968854f8a99ae47712c4f4183b78dcc4a903d1bfe8cbf60",_35 "0x86f78c5416151fe3546dece84fda4b4b1e36089f2dbc48496faf3a950f16157c",_35 "0x750839e9dbbd2a0910efe40f50b2f3b2f2f59f5580bb4b83bd8c1201cf9a010a",_35]_35_35module.exports = {_35 networks: {_35 development: {_35 provider: () => {_35 return new HDWalletProvider({_35 privateKeys: privateKeys,_35 providerOrUrl: provider,_35 })_35 },_35 network_id: "*",_35 gas: 3000000,_35 gasPrice: 225000000000,_35 },_35 },_35}
Note that you can change the protocol
, ip
and port
if you want to direct
API calls to a different Dijets node instance. Also note that we're setting the
gasPrice
and gas
to the appropriate values for the Dijets Utility Chain.
Add Storage.sol#
Storage is a solidity smart contract which lets us write a number to the
blockchain via a store
function and then read the number back from the
blockchain via a retrieve
function.
In the contracts
directory add a new file called Storage.sol
and add the following block of code:
_26pragma solidity >=0.4.22 <0.9.0;_26_26/**_26 * @title Storage_26 * @dev Store & retrieve value in a variable_26 */_26contract Storage {_26_26 uint256 number;_26_26 /**_26 * @dev Store value in variable_26 * @param num value to store_26 */_26 function store(uint256 num) public {_26 number = num;_26 }_26_26 /**_26 * @dev Return value_26 * @return value of 'number'_26 */_26 function retrieve() public view returns (uint256){_26 return number;_26 }_26}
Add New Migration#
Create a new file in the migrations
directory named 2_deploy_contracts.js
,
and add the following block of code. This handles deploying the Storage
smart
contract to the blockchain.
_10const Storage = artifacts.require("Storage")_10_10module.exports = function (deployer) {_10 deployer.deploy(Storage)_10}
Compile Contracts with Truffle#
Any time we make a change to Storage.sol
we need to run truffle compile
.
_10truffle compile
Accounts on Utility Chain#
When deploying smart contracts to the Utility Chain, truffle will default to the first
available account provided by your Utility Chain client as the from
address used
during migrations. We have added some pre-defined private keys as our accounts
in the truffle-config.json
. The first and default account should have some
pre-funded DJT.
Truffle Accounts#
You can view imported accounts with truffle console.
To open the truffle console:
_10truffle console --network development
Note: If you see Error: Invalid JSON RPC response: "API call rejected because chain is not done bootstrapping"
, you need to wait until network is
bootstrapped and ready to use. It should not take too long.
Inside truffle console:
_13truffle(development)> accounts_13[_13 '0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC',_13 '0x9632a79656af553F58738B0FB750320158495942',_13 '0x55ee05dF718f1a5C1441e76190EB1a19eE2C9430',_13 '0x4Cf2eD3665F6bFA95cE6A11CFDb7A2EF5FC1C7E4',_13 '0x0B891dB1901D4875056896f28B6665083935C7A8',_13 '0x01F253bE2EBF0bd64649FA468bF7b95ca933BDe2',_13 '0x78A23300E04FB5d5D2820E23cc679738982e1fd5',_13 '0x3C7daE394BBf8e9EE1359ad14C1C47003bD06293',_13 '0x61e0B3CD93F36847Abbd5d40d6F00a8eC6f3cfFB',_13 '0x0Fa8EA536Be85F32724D57A37758761B86416123'_13]
You can see balances with:
_10truffle(development)> await web3.eth.getBalance(accounts[0])_10'50000000000000000000000000'_10_10truffle(development)> await web3.eth.getBalance(accounts[1])_10'0'
Notice that accounts[0]
(default account) has some balance, while accounts[1]
has no balance.
Fund Your Account#
You'll to have a minimum of 0.15
DJT unlocked in your account to cover the cost
of contract deployments.
Personal APIs#
Personal APIs interact with node’s accounts. web3
has some functions that uses
it, e.g: web3.eth.personal.newAccount
, web3.eth.personal.unlockAccount
etc... However this API is disabled by default. It can be activated with
Utility Chain
/Coreth
configs. The Dijets Network Runner currently does not
support activating this API. So if you want to use these features you need to
run your own network manually with internal-private-personal
API enabled via
the eth-apis
flag. See Create a Local Test
Network/Manually and
Utility Chain Configs.
Run Migrations#
Now everything is in place to run migrations and deploy the Storage
contract:
_10truffle(development)> migrate --network development
If you didn't create an account on the Utility Chain you'll see this error:
_10Error: Expected parameter 'from' not passed to function.
If you didn't fund the account, you'll see this error:
_10Error: *** Deployment Failed ***_10_10"Migrations" could not deploy due to insufficient funds_10 * Account: 0x090172CD36e9f4906Af17B2C36D662E69f162282_10 * Balance: 0 wei_10 * Message: sender doesn't have enough funds to send tx. The upfront cost is: 1410000000000000000 and the sender's account only has: 0_10 * Try:_10 + Using an adequately funded account
Interacting with Your Contract#
Now the Storage
contract has been deployed. Let's write a number to the
blockchain and then read it back. Open the truffle console again:
Get an instance of the deployed Storage
contract:
_10truffle(development)> let instance = await Storage.deployed()
Writing a number to the blockchain#
Now that you have an instance of the Storage
contract, call it's store
method and pass in a number to write to the blockchain.
_10truffle(development) > instance.store(1234)
Reading a Number from Dijets Utility Chain#
To read the number from Dijets Utility Chain, call the retrieve
method of the Storage
contract instance we deployed earlier.
_10truffle(development)> let i = await instance.retrieve()
The result of the call to retrieve
is a BN
(big number). Call its .toNumber
method to see the value:
_10truffle(development) > i.toNumber()
Summary#
Now you have the tools you need to launch a local Dijets network, create a truffle project, as well as create, compile, deploy and interact with Solidity contracts.