wscip

Smart Contract Invocation Protocol wrapper

Usage no npm install needed!

<script type="module">
  import wscip from 'https://cdn.skypack.dev/wscip';
</script>

README

SCIP for Node.js

An asynchronous Smart Contract Invocation Protocol wrapper library written in typescript. The source code of this module can be found in the wscip repository.

Version: 1.0.0

Date: November 16, 2019

Author: Andrea Lamparelli

Requirements: Axios (Promise based HTTP client for the browser and node.js)

For more details about Smart Contract Invocation Protocol, please refer to this Github repository.

Table of Contents

Installation

The module can be installed with npm using the following command:

npm install wscip

Quick Start

Before start, be sure that the target endpoint is a valid SCIP endpoint (for more information about which kind of request it should be able to understand, please refer to this Github repository).

const wscip = require('wscip');		// javascript
import { SCIP, Target } from 'wscip';		// typescript

Once you have imported the module, you have to simply retrieve the domain that identifies the SCIP gateway to which you want to perform the requests. Then create a ```SCIP`` object passing the gateway domain as parameter.

var client = wscip.SCIP(domain);	// javascript
var client = SCIP(domain);			// typescript

Now that you have the SCIP object created, you can perform the SCIP supported operations by simply by simply invoking the appropriate SCIP function.

Requests

As defined in the scip specification, you can perform four different types of operations:

  • Function invocation
  • Function/Event subscription
  • Cancel subscription
  • Query previous event occurrences or function invocations

Note: this library is Promise-based, hence each SCIP request returns a Promise object that should be handled accordingly.

Data Types

In order to make SCIP request invocation easier for the client, this library uses some predefined types which define the structure needed for every allowed invocation:

The ISCLQuery object is used to identify a specific smart contract from the outside of the blockchain itself, for more details see SCL specification.

ISCLQuery {
    /** blockchain where the smart contract is host */
    blockchain: string;
    /** blockchain network identifier */
    blockchain_id: string;
    /** smart contracts' blockchain internal address */
    address: string;
}

The IParam defines the generic structure of a parameter, which can be either an input or an output parameter.

IParam {
      /** name of the parameter */
      name: string;
      /** JSON-schema type of the parameter */
      absType: string;
      /** wheter it is an input parameter or an output one */
      isInput: boolean;
      /** [optional] runtime value of the parameter */
      value?: any;
}

The IInvocation defines the structure needed to invoke a smart contract's function.

Invocation {
      /** the programmatic name of the function */
      identifier: string;
      /** the list of parameters to be passed to the function */
      inputs: IParam[];
      /** the list of parameters to be returned from the function */
      outputs: IParam[];
      /** the URL to which the callback message will be sent */
      callback: string;
      /** the client's digital signature of the other components of the request message */
      signature: string;
      /** the DoC required from the resuting transaction (degree of confidence) */
      corrId?: string;
      /** a client-generated identifier that will be copied to the callback message for correlation purposes */
      doc?: number;
}

The ISubscription provides a generic structure, required for subscription operations, either for events or for functions.

ISubscription {
      /** the identifier of the event to be monitored */
      identifier: string;
      /** the list of outputs parameter used to identify the event */
      params: IParam[];
      /** the URL to which the callback message will be sent */
      callback: string;
      /** the DoC required from the corresponding transaction (degree of confidence) */
      doc?: number;
      /** the client-provided correlation identifier */
      corrId?: string;
      /** a C-style boolean expression to select only certain event occurrences */
      filter?: string;
}

The ICancellation defines the generic structure needed for subscription cancellation operations, either for functions or events.

ICancellation {
      /** the identifier of the function/event whose subscriptions are to be canceled */
      identifier: string;
      /** the list of input/output parameters used to identify the function/event respectively */
      params: IParam[];
      /** the client-provided correlation identifier */
      corrId: string;
}

The IQuery states the generic structure for a query operation, either for function or for events.

IQuery {
      /** the identifier of the function/event to be queried */
      identifier: string;
      /** the list of input/output parameters used to identify the function/event respectively */
      params: IParam[];
      /** ISO Date-Time describing the starting point in time at which occurrences/invocations are considerd */
      startTime?: string;
      /** ISO Date-Time describing the ending point in time at which occurrences/invocations are considerd */
      endTime?: string;
      /** a C-style boolean expression to select only certain event occurrences */
      filter?: string;
}

Function Invocation

For smart contract's function invocation you will have to just call the function invoke on you client object:

client.invoke(
    '1',  // JSON-RPC identifier, client-provided
    {	// this object identifies the smart contract
        blockchain: 'ethereum',
        blockchain_id: '4',
        address: '0x45rf6....'
    },
    {	// this object contains all parameters needed for function invocation
        identifier: 'addDigest',  // smart contract's function name to invoke
        inputs: [{name: 'digest', absType: 'string', isInput: true, value: '854234802'}],
        outputs: [],
        callback: <url>,  // url to which the gateway will redirect the async responses
        signature: <signature>,  // digital signature of other request's components
        corrId: <correlation-identifier>,
        doc: 99.8  // Degree of Confidence
    }
).then(
    res => .. // handle the JSON-RPC response
).catch(
    err => .. // handle the JSON-RPC error
)

Subscription

Here, you just have to call subscribe function:


client.subscribe(
    '2',  // JSON-RPC identifier, client-provided
    {	// this object identifies the smart contract
        blockchain: 'ethereum',
        blockchain_id: '4',
        address: '0x9835h3t48t34t9j3'
    },
    {
        identifier: 'Add',
        params: [{name: 'corrId', absType: 'string', isInput: false}],
        callback: 'http://localhost:4200',
        corrId: 'id1',
        filter: 'corrId == 1'
    },
    Target.EVENT  // subscribe an event, (or wscip.Target.EVENT)
).then(
    res => .. // handle the JSON-RPC response
).catch(
    err => .. // handle the JSON-RPC error
)

Cancellation

Here, you just have to call cancel function as follows:

client.cancel(
    '3',  // JSON-RPC identifier, client-provided
    {	// this object identifies the smart contract
        blockchain: 'ethereum',
        blockchain_id: '4',
        address: '0x9835h3t48t34t9j3'
    },
    {
        identifier: 'Add',
        params: [{name: 'corrId', absType: 'string', isInput: false}],
        corrId: 'id1'
    },
    wscip.Target.EVENT  // cancel a previously created event subscription, (or wscip.Target.EVENT)
).then(
    res => console.log(res.data)
).catch(
    err => console.error(err)
)

Query

For query operation you just have to call query function, as follows:

client.query(
    '4',  // JSON-RPC identifier, client-provided
    {	// this object identifies the smart contract
        blockchain: 'ethereum',
        blockchain_id: '4',
        address: '0x9835h3t48t34t9j3'
    },
    {
        identifier: 'Add',
        params: [{name: 'corrId', absType: 'string', isInput: false}],
        filter: 'corrId != "id1"',
        startTime: <iso-time>,  // starting point ISO date-time
        endTime: <iso-time>  // ending point ISO date-time
    },
    wscip.Target.EVENT  // query an event, (or wscip.Target.EVENT)
).then(
    res => console.log(res.data)
).catch(
    err => console.error(err)
)

Questions and Contributing

Feel free to post questions and problems on the issue tracker. Pull requests are welcome!

Feel free to fork and modify or add new features and functionality to the library