Corda Automation Testing with Nightwatch.js and CircleCI

Testing is an integral part of software development. In Chainstack, we do not only test the platform but also ensure all blockchain protocols work perfectly. In this post, I will share how we carry out end-to-end continuous Corda integration with Nightwatch.js and CircleCI.

The code in Corda is written using Kotlin, a programming language from JetBrains, and Nightwatch.js is a Node.js powered end-to-end testing framework. Our challenges are to connect to a node, initiate a flow, and have it signed by relevant parties using JavaScript.

We have a few ideas to do this:

  • Run a Corda web server in our Docker image, and write JavaScript to interact to the CorDapp.
  • Set up GraalVM (a high-performance polyglot VM) in our Docker image, write a Java function in Nightwatch.js.
  • Interact with Corda Standalone Shell client by executing a shell script in Node.js, then verify the output of the shell script.

The first two ideas seem possible, but we need to include CorDapp source code in the test, which is non-optimal and inconvenient. Eventually, the last one is better and simpler.

We use No ticket scalping CorDapp for our test. You may want to explore it before moving to details.

Technology stack

These are the details of programming languages, tools, and frameworks we used in the test:

I assume that you are familiar with the Nightwatch.js framework, so I won’t focus on the structure as well as the test case code.

Besides the Corda Standalone Shell client, Chainstack also provides Chainstack standalone shell, which is a containerized version of Corda Standalone Shell, and which helps you interact with the CorDapps. You can learn more about it in our official documentation.

Node details and credentials in Chainstack.

Install OpenJDK-8 in Docker image

You need to install OpenJDK-8 to run Corda Standalone Shell client; add the following lines into your Docker file.

# Install OpenJDK-8
RUN apt-get update && \
    apt-get install -y openjdk-8-jdk && \
    apt-get install -y ant && \
    apt-get clean;

# Fix certificate issues
RUN apt-get update && \
    apt-get install ca-certificates-java && \
    apt-get clean && \
    update-ca-certificates -f;

# Setup JAVA_HOME -- useful for docker commandline
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64/
RUN export JAVA_HOME

You may need to build your Docker image again.

docker build .

Write a shell script to interact with No ticket scalping CorDapp

You can learn the prerequisites to run Corda Standalone Shell client at Chainstack Docs.

The below script will do the following things:

  • Connect to Corda Node 1.
  • Print out all flows in Node 1.
  • Start noScalpFlow flow to distribute 99 tickets of event Chainstack live concert from Node 1 to Node 2.
  • Verify the transaction by executing the vaultQuery command.
  • Exit the Corda Standalone Shell client.
# location of binary files
CORDA_CLI="corda-tools-shell-cli-4.3-all.jar"
CORDAPP_DIR="../my-cordapps/"

# node 1 credentials
NODE1_HOST="nd-255-728-694.rg-837-380.int.chainstack.com"
NODE1_PORT="10201"
NODE1_USER="vibrant_ptolemy"
NODE1_PASS="*****"

# node 2 legal name
NODE2_LEGALNAME="OU=Chainstack-ND-026-270-261, O=Chainstack, L=Singapore, C=SG"

# command to connect to Corda node 1
START_CORDAPP="java -jar $CORDA_CLI --host=$NODE1_HOST --port=$NODE1_PORT --user=$NODE1_USER --password=$NODE1_PASS --cordapp-directory=$CORDAPP_DIR"

# launch the Corda Standalone Shell client and run flow commands
{
  echo "flow list"
  echo "start noScalpFlow eventName: 'Chainstack live concert', ticketQuantity: 99, toDistributor: '$NODE2_LEGALNAME'"
  echo "run vaultQuery contractStateType: com.noScalpDapp.states.noScalpState"
  echo "bye"
} | $START_CORDAPP

Save as a start_cordapp.sh file, and run it in the terminal.

Interact with CorDapp in terminal.

Checking the output, there should be a transaction. You can use this information to verify whether the test passed or not.

Flow completed with result: SignedTransaction(id=C98A2B49358B9FC6C1C8EEBAA99DF36238E9E4F97CF492905C2A1EF25B1B9639)

Execute the shell script by Node.js and verify the output

In the below code, I write a function to start the noScalpFlow flow, print out, and verify its result. In Node.js, the child_process module provides the ability to spawn child processes.

Then, I combine child_process.exe() and util.promisify() to create an async function which returns a boolean Promise.

// Nodejs utils to execute the shell script asynchronously
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);

/**
 * Run noScalpFlow flow and verify the result
 * @param {Object} node1 First node
 * @param {Object} node2 Second node
 */
async function verifyFlow(node1, node2) {
  const CORDA_CLI = 'corda-tools-shell-cli-4.3-all.jar';
  const CORDAPP_DIR = '../my-cordapps/';
  const START_CORDAPP = `java -jar ${CORDA_CLI} --host=${node1.host} --port=${node1.port} --user=${node1.user} --password=${node1.pass} --cordapp-directory=${CORDAPP_DIR}`;  

  // launch the Corda Shell client and run flow commands
  const { stdout } = await exec(`
    START_CORDAPP="${START_CORDAPP}"
    {
      echo "flow list"
      echo "start noScalpFlow eventName: 'Chainstack live concert', ticketQuantity: 99, toDistributor: '${node2.legalName}'"
      echo "run vaultQuery contractStateType: com.noScalpDapp.states.noScalpState"
      echo "bye"
    } | $START_CORDAPP
  `);  

  // Print out the output
  console.log(stdout);  

  // Verify the output
  return stdout.includes('Flow completed with result: SignedTransaction');
}

After that, you need a test scenario using the Nightwatch.js framework.

// Node 1 credentials
const node1 = {
  host: 'nd-255-728-694.rg-837-380.int.chainstack.com',
  port: '10201',
  user: 'vibrant_ptolemy',
  pass: '*****',
};

// Node 2 legal name
const node2 = {
  legalName: 'OU=Chainstack-ND-026-270-261, O=Chainstack, L=Singapore, C=SG',
};

module.exports = {
  '@tags': ['runCorDappFlow'],  

  'Run CorDapp flow'(browser) {
    const { page } = browser;
    const corda = page.nodes.corda();    

    // Run flow and verify result
    browser.perform(async () => {
      await corda.verifyFlow(node1, node2);
    });    
    
    browser.end();
  },
};

Commit your code and run the workflow in CircleCI; it will take a few minutes to complete. In my scenario, I get the credentials of Node 1 and Node 2, run the noScalpFlow flow, and verify the output. You can see the results in the below screenshot.

Running CorDapp flow in CircleCI.

Before writing this post, I have done a lot of research to find the best solution for Corda automation testing as most of the resources from the Internet focus on building CorDapps. I believe this post will help your team to test, speed up, and secure your Corda applications like what the Chainstack team is doing.

You can try Chainstack for free at https://console.chainstack.com.

The Ethereum Cloud vs. On-Premises Nodes Conundrum

Is there a way to actually identify how many Ethereum nodes are running in cloud and on-premises? There is, and it’s easy enough. In this article, we are going to get the Ethereum mainnet node data and have a look…

Evgeny Konstantinov
Evgeny Konstantinov
Sep 24
Chainstack uses cookies to provide you with a secure and
personalized experience on its website. Learn more.