Input Specification File

The Blockchain App Builder initialization command reads the input specification file and generates the scaffolded project with several tools to assist in the chaincode development process.

With the specification file you can specify multiple asset definitions and behavior, CRUD and non-CRUD method declaration, custom methods, validation of arguments, auto marshalling/unmarshalling, transparent persistence capability, and invoking rich data queries using SQL SELECTs or CouchDB Query Language. These features will be generated for you.

The specification file can be written in either yaml or json. You can see sample specification files in both formats in the Blockchain App Builder package download:
  • fabcar.yml
  • marbles.yml

Note:

As per Go conventions, exported names begin with a capital letter. Therefore all the asset properties and methods must have names starting with capital letters in the specification file.

Structure of the Specification File

The specification file should be structured in the following way:

assets: 
    name:
    properties:
        name:
        type:
        id:
        derived:
           strategy:
           algorithm:
           format:
        mandatory:
        default:
        validate:
    methods:
        crud:
        others:
    type:
customMethods:

Table C-2 Specification File Parameter Descriptions and Examples

Entry Description Examples
assets:

This property takes the definition and behavior of the asset. You can give multiple asset definitions here.

 
name:

The name of the asset.

name: owner # Information about the owner
properties:

Describe all the properties of an asset.

 
name:

The name of the property.

name: ownerId # Unique ID for each owner
type:
Basic types are supported:
  • number
  • string
  • boolean
  • date
  • array
  • embedded
For Go chaincodes, number is mapped to init. Other types such as
  • float
  • complex
  • unsigned/signed int
  • 8/16/32/64 bits
are not supported at this time.
name: year        # Model year
type: number
mandatory: true
validate: min(1910),max(2020)
name: color       # Color - no validation as color names are innumerable
type: string
mandatory: true
id:
  • true

This specifies the identifier of this asset. This property is mandatory.

name: owner            # Informmation about the owner
properties:
     name: ownerId    # Unique ID for each owner
     type: string
     mandatory: true
     id: true
     name: name        # Name of the owner
     type: string
     mandatory: true
derived:

This property specifies that the id property is derived from other keys. Dependent properties should be string datatype and not an embedded asset.

This property has two mandatory parameters:
  • strategy: takes values of concat or hash.
  • format: takes an array of specification strings and values to be used by the strategy.
Example 1:
  • The property employeeID is dependent on the firstName and lastName properties.
  • This property is a concatenation of the values listed in the format array.
  • IND%1#%2%tIND is the 0th index in the array and describes the final format.
  • %n is a position specifier that takes its values from the other indexes in the array.
  • %t indicates the value should be stub.timestamp from the channel header.
  • If you need to use the character % in the format string, it should be escaped with another %.
  • The final format in this example would be: INDfirstName#lastName1606885454916IND
Example 2:
  • When using hash, you must also use the algorithm parameter. The default is sha256; md5 is also supported.
  • IND%1#%2%t is the 0th index in the array and describes the final format.
  • %n is a position specifier that takes its values from the other indexes in the array.
  • %t indicates the value should be stub.timestamp from the channel header.
  • If you need to use the character % in the format string, it should be escaped with another %.
Example 1
name: employee
  properties:
     name: employeeId
     type: string
     mandatory: true
     id: true
     derived:
         strategy: concat
         format: ["IND%1#%2%tIND","firstName","lastName"]

     name: firstName
     type: string
     validate: max(30)
     mandatory: true

     name: lastName
     type: string
     validate: max(30)
     mandatory: true

     name: age
     type: number
     validate: positive(),min(18)
Example 2
name: account
  properties:
     name: accountId
     type: string
     mandatory: true
     id: true
     derived:
         strategy: hash
         algorithm: 'sha256'
         format: ["IND%1#%2%t","bankName","ifsccode"]

     name: bankName
     type: string
     validate: max(30)
     mandatory: true

     name: ifsccode
     type: string
     mandatory: true
mandatory:
  • true
  • false

The corresponding property is mandatory and cannot be skipped while creating an asset.

name: phone       # Phone number - validate as (ddd)-ddd-dddd where dashes could also be periods or spaces
type: string
mandatory: true
validate: /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/
name: cars        # The list of car VINs owned by this owner
type: string[]
mandatory: false
default:

This gives you the default value of this property.

 
validate:

The given property is validated against some of the out-of-box validations provided by Blockchain App Builder. You can chain validations if you ensure that the chain is valid.

If the validate property is not provided, then the validation is done against only the property type.

 
validate:

type: number

  • positive()
  • negative()
  • min()
  • max()

These validations can be chained together separated by commas.

name: offerApplied
type: number
validate: negative(),min(-4)
name: year  # Model year
type: number
mandatory: true
validate: min(1910),max(2020)
validate:

type: string

  • min()
  • max()
  • email()
  • url()
  • /regex/ - supports PHP regex

For Go chaincodes, regular expressions which contain certain reserved characters or whitespace characters should be properly escaped.

name: website 
type: string
mandatory: false
validate: url()
name: phone  # Phone number - validate as (ddd)-ddd-dddd where dashes could also be periods or spaces
type: string
mandatory: true
validate: /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/
name: Color #Color can be red, blue, or green
type: string
mandatory: true
validate: /^\\s*(red|blue|green)\\s*$/
validate:

type: boolean

  • true
  • false

In the example, the validation of property active is by the type itself (boolean)

name: active
type: boolean
validate:

type: array

By type itself, in the form of type: number[], this conveys that the array is of type number.

You can enter limits to the array in the format number[1:5] which means minimum length is 1, maximum is 5. If either one is avoided, only min/max is considered.

name: items
type: number[:5]
validate:

type: date

  • min()
  • max()
Date should be one of these formats:
  • YYYY-MM-DD
  • YYYY-MM-DDTHH:MM:SSZ, where T separates the date from the time, and the Z indicates UTC. Timezone offsets can replace the Z as in -05:00 for Central Daylight Savings Time.
name: expiryDate
type: date
validate: max('2020-06-26')
name: completionDate
type: date
validate: min('2020-06-26T02:30:55Z')
methods:

Use this to state which of the CRUD (Create/Read/Update/Delete) or additional methods are to be generated.

By default, if nothing is entered, all CRUD and other methods are generated.

methods:
    crud: [create, getById, update, delete]
    others: [getHistoryById, getByRange]
crud:
  • create
  • getByID (read)
  • update
  • delete

If this array is left empty, no CRUD methods will be created.

If the crud parameter is not used at all, all four methods will be created by default.

methods:
    crud: [create, getById, delete]
    others: [] # no other methods will be created
others:
  • getHistoryById
  • getByRange

getHistoryById returns the history of the asset in a list.

getByRange returns all the assets in a given range.

If this array is left empty, no other methods will be created.

If the others parameter is not used at all, both methods will be created by default.

methods:
    crud: [create, delete]
    others: [] # no other methods will be created
      methods:
        crud: [create, getById, update, delete]
        others: [getHistoryById, getByRange]
type:

This attribute if set to embedded defines the asset as an embedded asset. Embedded assets do not have CRUD methods and have to be part of another asset to store in the ledger.

In the example, the property address is embedded, and is defined in another asset.

Asset: employee
name: employee
  properties:
     name: employeeId
     type: string
     mandatory: true
     id: true

     name: firstName
     type: string
     validate: max(30)
     mandatory: true

     name: lastName
     type: string
     validate: max(30)
     mandatory: true

     name: age
     type: number
     validate: positive(),min(18)

     name: address
     type: address
Asset: address
name: address

type: embedded

properties:
   name: street
   type: string

   name: city
   type: string

   name: state
   type: string

   name: country
   type: string
customMethods:

This property creates invokable custom method templates in the main controller file. It takes the method signature and creates the function declaration in the controller file.

You can provide language specific function declarations here.

We provide a custom method named executeQuery. If it's added to the specification file, it details how Berkeley DB SQL and CouchDB rich queries can be executed. This method can be invoked only when you are connected to Oracle Blockchain Platform Cloud or Enterprise Edition.

TypeScript

customMethods:
    - executeQuery
    - "buyCar(vin: string, buyerId: string, sellerId: string, price: number, date: Date)"
    - "addCar(vin: string, dealerId: string, price: number, date: Date)"

Go

customMethods:
    - executeQuery
    - "BuyCar(vin string, buyerId string, sellerId string, price int)"
    - "AddCar(vin string, dealerId string, price int)"