Truffle

Truffle is supported via Janus and there are two ways to get it working.

  • By loading private keys into Janus/Qtum

  • Using @qtumproject/hdwallet-provider

Lets unbox an example truffle box and walk through running a migration

First, go to an empty directory and create a new directory and unbox

mkdir react-box
cd react-box
truffle unbox qtumproject/react-box

Output should look like this

Starting unbox...
=================

✔ Preparing to download box
✔ Downloading
✔ Cleaning up temporary files
✔ Setting up box

Unbox successful, sweet!

Commands:

  Compile:              truffle compile
  Migrate:              truffle migrate
  Test contracts:       truffle test
  Test dapp:            cd client && npm test
  Run dev server:       cd client && npm run start
  Build for production: cd client && npm run build

Next, install dependencies

npm install

Generating a BIP44 mnemonic to use with truffle

You can use Mnemonic Code Converter to generate a mnemonic for local development

  • if you plan on using this tool for mainnet, you can download a release and run it completely offline.

And then lets take a look at the truffle-config.js file

Here, you will need to copy your mnemonic into the regtest mnemonic space

const HDWalletProvider = require("@qtumproject/hdwallet-provider");

module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // for more about customizing your Truffle configuration!
  networks: {
    // The Janus node has private keys hosted
    janus: {
      host: "127.0.0.1",
      port: 23889,
      network_id: "*",
    },
    regtest: {
      provider: () => new HDWalletProvider({
        mnemonic: "erode phrase labor rack surge risk armor uniform together prevent crack alley",
        providerOrUrl: "http://localhost:23889",
      }),
      gasPrice: "0x5d21dba000"
    },
    testnet: {
      provider: () => new HDWalletProvider({
        mnemonic: "",
        providerOrUrl: "https://testnet-janus.qiswap.com/api/",
      }),
      gasPrice: "0x5d21dba000"
    },
    mainnet: {
      provider: () => new HDWalletProvider({
        mnemonic: "",
        providerOrUrl: "https://janus.qiswap.com/api/",
      }),
      gasPrice: "0x5d21dba000"
    },
  },
  compilers: {
    solc: {
      version: "^0.8.0",
      settings: {
        optimizer: {
          enabled: true,
          runs: 1,
        },
      },
    },
  },
};

Launching Janus/Qtum

# Configure Docker networking (only need be done once)
docker network create --driver bridge qtum

# Launch Qtum regtest
docker run --network=qtum -it --rm \
  --name qtumd_regtest \
  -v `pwd`:/root \
  -p 23888:23888 \
  -p 3889:3889 \
  qtum/qtum \
  qtumd -regtest -txindex -addrindex=1 -logevents \
  -rpcbind=0.0.0.0:3889 -rpcallowip=0.0.0.0/0 -rpcuser=qtum -rpcpassword=testpasswd

# Launch Janus
docker run --network=qtum -it --rm \
  --name janus_regtest \
  -v `pwd`:/root \
  -p 23889:23889 \
  qtum/janus:latest \
  --bind 0.0.0.0 --dev --qtum-rpc=http://qtum:testpasswd@qtumd_regtest:3889

Seeding regtest with Qtum

You can get your address from the truffle console once Qtum is running.

truffle console --network regtest

truffle(regtest)> accounts
[
  '0x63c4953002B935C3CA925af419DFCE86C057AB95',
  '0xEccAAa32664B8499931DFB4aFD076a61e01C12F8',
  '0xB118812cCb1C79a6d0849D5393Ee6475Da5b8bdE',
  '0x733722f989763E4243D82FB8667d6DEB08BEC2A8',
  '0xe2ce59EBaC7c1B129c5623B105D62aD64eDDe645',
  '0x2974BE44127169546fC09E7C251C757892C0E990',
  '0x26c0573F40B575F663CD846Fc2D811C13a61866d',
  '0x175eE832683EbE001f01C7c944e585cD799FacB6',
  '0xC76e10C8B54e942a5b9C6E024571D4A2A9fd4a4B',
  '0x9014cedEDF69C02b43a46e414Ac643281A14acd3'
]

Then you can seed regtest using either qtum-cli or Janus

  • note that fromhexaddress requires dropping the hex prefix 0x

  • Qtum block rewards need to be at least 2000 blocks old to be used

# Get base58 address from hex
docker exec qtumd_regtest \
  qtum-cli \
  -rpcuser=qtum \
  -rpcpassword=testpasswd \
  fromhexaddress 63c4953002B935C3CA925af419DFCE86C057AB95

> qSeuYqETzKqcVn3seaTRQ1U8jcaR1QHYQj

# Seed regtest with Qtum
docker exec qtumd_regtest \
  qtum-cli \
  -rpcuser=qtum \
  -rpcpassword=testpasswd \
  generatetoaddress 2005 qSeuYqETzKqcVn3seaTRQ1U8jcaR1QHYQj

# Or do it in one command
docker exec qtumd_regtest \
  qtum-cli \
  -rpcuser=qtum \
  -rpcpassword=testpasswd \
  generatetoaddress 2005 `\
    docker exec qtumd_regtest \
      qtum-cli \
      -rpcuser=qtum \
      -rpcpassword=testpasswd \
      fromhexaddress 63c4953002B935C3CA925af419DFCE86C057AB95`

Or you can use dev_generatetoaddress Janus RPC call to do this

  • note that generating this many blocks will cause Janus to timeout waiting for a response from Qtum, but Qtum will still generate the blocks

# Directly calling dev_generatetoaddress via Curl
curl --location --request POST 'http://localhost:23889' \
  --header 'Content-Type: text/plain' \
  --data-raw '{
    "method": "dev_generatetoaddress",
    "params": [
      2005,
      "63c4953002B935C3CA925af419DFCE86C057AB95"
    ]
  }'

# response
{"jsonrpc":"2.0","result":["1369920b45f482096b2159788c2f1cd576b0e37affc176df07904d8a841f8590", ...]}

truffle migrate

Now that your local regtest environment has Qtum we can deploy code with truffle

truffle migrate --network regtest

Compiling your contracts...
===========================
 Fetching solc version list from solc-bin. Attempt #1
> Everything is up to date, there is nothing to compile.



Starting migrations...
======================
> Network name:    'regtest'
> Network id:      8890
> Block gas limit: 40000000 (0x2625a00)


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0x867d80074f084e27ae2828dea3bd6384d18d4dd3e8a20bafefa1578dff38a726
   > Blocks: 0            Seconds: 0
   > contract address:    0x676BC04885F727b393b7d8788E54f0BC47888b0c
   > block number:        2008
   > block timestamp:     1657302875
   > account:             0x63c4953002B935C3CA925af419DFCE86C057AB95
   > balance:             40099999.836968
   > gas used:            130690 (0x1fe82)
   > gas price:           400 gwei
   > value sent:          2.690858 ETH
   > total cost:          2.743134 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:            2.743134 ETH


2_deploy_contracts.js
=====================

   Deploying 'SimpleStorage'
   -------------------------
   > transaction hash:    0x7e3fa9e99d9954820bf2f12f4335b5dbf19a1bab409a096de61e526225ca60d2
   > Blocks: 0            Seconds: 0
   > contract address:    0xa9052BAfE2d784990F8a99ED69dcB11c147B084C
   > block number:        2010
   > block timestamp:     1657302877
   > account:             0x63c4953002B935C3CA925af419DFCE86C057AB95
   > balance:             40099999.779758
   > gas used:            90527 (0x1619f)
   > gas price:           400 gwei
   > value sent:          2.690442 ETH
   > total cost:          2.7266528 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:           2.7266528 ETH


Summary
=======
> Total deployments:   2
> Final cost:          5.4697868 ETH

Artifacts will be in build/contracts/*.json

tail -n 22 build/contracts/*.json            
==> build/contracts/Migrations.json <==
  "networks": {
    "8890": {
      "events": {},
      "links": {},
      "address": "0x676BC04885F727b393b7d8788E54f0BC47888b0c",
      "transactionHash": "0x867d80074f084e27ae2828dea3bd6384d18d4dd3e8a20bafefa1578dff38a726"
    }
  },
  "schemaVersion": "3.3.4",
  "updatedAt": "2022-07-08T17:54:38.284Z",
  "networkType": "ethereum",
  "devdoc": {
    "kind": "dev",
    "methods": {},
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  }
}
==> build/contracts/SimpleStorage.json <==
  "networks": {
    "8890": {
      "events": {},
      "links": {},
      "address": "0xa9052BAfE2d784990F8a99ED69dcB11c147B084C",
      "transactionHash": "0x7e3fa9e99d9954820bf2f12f4335b5dbf19a1bab409a096de61e526225ca60d2"
    }
  },
  "schemaVersion": "3.3.4",
  "updatedAt": "2022-07-08T17:54:38.282Z",
  "networkType": "ethereum",
  "devdoc": {
    "kind": "dev",
    "methods": {},
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  }
}%

Last updated