Samples

One of the great things about having an OpenAPI (pka Swagger) definition of your contract, is you can use simple API libraries to invoke your smart contract methods.

This is true of course for a huge range of languages - Java, Microsoft .NET, Go, Python, Ruby and more.

In these samples we pick one - Javascript (Node.js) to give you an starting point demonstrating for how similar deploying, and accessing your Smart Contract business logic is with Kaleido to any other modern REST API.

Smart Contract source

The samples below use this file as simplestorage.sol:

pragma solidity >0.4.24;

contract SimpleStorage {

    event ValueChanged(address indexed author, string oldValue, string newValue);

    string storedValue;

    constructor(string memory newValue) public {
        emit ValueChanged(msg.sender, storedValue, newValue);
        storedValue = newValue;
    }

    function getValue() public view returns (string memory value) {
        return storedValue;
    }

    function setValue(string memory newValue) public {
        emit ValueChanged(msg.sender, storedValue, newValue);
        storedValue = newValue;
    }
}

Node.js Pre-reqs

npm install swagger-client request-promise-native

Deploying and Invoking a Smart Contract

In this sample we deploy a smart contract, then access it.

Change the following:

  • NODE_URL - the -connect URL for the node, such as
    https://u0j6rld2ka-u0uk478rin-connect.us0-aws.kaleido.io
  • FROM_ADDRESS - one of the address from the Wallet of that node (see the wallet tab on the Node details panel)
  • USERNAME - from a valid application credential for the node
  • PASSWORD - from a valid application credential for the node
const request = require('request-promise-native')
const filePath = "./simplestorage.sol";
const fs = require('fs')
const Swagger = require('swagger-client');
const {URL} = require('url');

const NODE_URL = `https://YOURENV-YOURNODE-connect.us0-aws.kaleido.io`;
const FROM_ADDRESS = "CHANGE ME";
const USERNAME = "CHANGE ME";
const PASSWORD = "CHANGE ME";

function authHelper(username, password) {
  return req => {
    req.headers.authorization = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`;
  }
}
async function deploy() {

  // Teach the REST API Gateway about our solidity code
  const url = new URL(NODE_URL);
  url.username = USERNAME;
  url.password = PASSWORD;
  url.pathname = "/abis";
  const req = request.post({
    url: url.href,
    qs: { compiler: "0.5" }
  });
  req.form().append("file", fs.createReadStream(filePath));

  // Retrieve a Gateway API that can:
  // - get data from any existing deployed contract that conforms to the ABI
  // - deploy new instances of the contract
  // - subscribe for events that match the signatures in this ABI (globally or on specific instances)
  console.log('Generating Gateway API');
  const { openapi } = await req.json();

  // Create a Swagger client for the OpenAPI specification we just downloaded
  console.log('Downloading OpenAPI defintion for Gateway API');
  let client = await Swagger(openapi, {
    requestInterceptor: authHelper(USERNAME,PASSWORD) // Include security credentials
  });

  // Invoke the constructor with arguments to deploy a new instance
  console.log('Deploying Contract Instance via Gateway API');
  const deploy = await client.apis.default.constructor_post({
    body: {
      // Here we set the constructor parameters
      newValue: "11111111"
    },
    "kld-from": FROM_ADDRESS
  });

  // Retrieve the address of the deployed contract
  let {contractAddress} = deploy.body;

  // Query the contract using the Gateway API (that can talk to any contract)
  console.log('Getting initial value via the getValue() method of the contract');
  const result = await client.apis.default.getValue_get({address: contractAddress});
  console.log(`Initial Value: ${JSON.stringify(result.body)}`);

  // Update the conract by submitting a transaction
  console.log('Setting value via the setValue() method of the contract');
  const resultPost = await client.apis.default.setValue_post({
    body: {
      newValue: "22222222"
    },
    "kld-from": FROM_ADDRESS,
    "kld-sync": "true", // Block waiting for the response, rather than using full TX streaming
    address: contractAddress,
  });
  console.log(`Update TX hash: ${JSON.stringify(resultPost.body.transactionHash)}`);

  // Query the value again from the contract
  const resultNew = await client.apis.default.getValue_get({
    address: contractAddress
  });
  console.log(`Updated Value: ${JSON.stringify(resultNew.body)}`);

}
deploy().catch(err => {
  console.error(err.stack);
  process.exit(1);
});