Home

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.

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:


_10
cd /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:


_10
cd /path/to/directory

Create and enter a new directory named truffle:


_10
mkdir 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.


_10
npm 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:


_10
truffle 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.


_10
npm 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.


_35
const Web3 = require("web3")
_35
const HDWalletProvider = require("@truffle/hdwallet-provider")
_35
_35
const protocol = "http"
_35
const ip = "localhost"
_35
const port = 9650
_35
Web3.providers.HttpProvider.prototype.sendAsync =
_35
Web3.providers.HttpProvider.prototype.send
_35
const provider = new Web3.providers.HttpProvider(
_35
`${protocol}://${ip}:${port}/ext/bc/C/rpc`
_35
)
_35
_35
const privateKeys = [
_35
"0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027",
_35
"0xbbc2865b76ba28016bc2255c7504d000e046ae01934b04c694592a6276988630",
_35
"0xcdbfd34f687ced8c6968854f8a99ae47712c4f4183b78dcc4a903d1bfe8cbf60",
_35
"0x86f78c5416151fe3546dece84fda4b4b1e36089f2dbc48496faf3a950f16157c",
_35
"0x750839e9dbbd2a0910efe40f50b2f3b2f2f59f5580bb4b83bd8c1201cf9a010a",
_35
]
_35
_35
module.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:


_26
pragma solidity >=0.4.22 <0.9.0;
_26
_26
/**
_26
* @title Storage
_26
* @dev Store & retrieve value in a variable
_26
*/
_26
contract 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.


_10
const Storage = artifacts.require("Storage")
_10
_10
module.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.


_10
truffle 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:


_10
truffle 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:


_13
truffle(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:


_10
truffle(development)> await web3.eth.getBalance(accounts[0])
_10
'50000000000000000000000000'
_10
_10
truffle(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:


_10
truffle(development)> migrate --network development

If you didn't create an account on the Utility Chain you'll see this error:


_10
Error: Expected parameter 'from' not passed to function.

If you didn't fund the account, you'll see this error:


_10
Error: *** 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:


_10
truffle(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.


_10
truffle(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.


_10
truffle(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:


_10
truffle(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.