Asset Framework
Introduction
The Asset Framework is a tool designed to help kickstart the development of asset-tracking based apps on the STRATO Mercata network. It allows for faster deployment of Dapps on STRATO Mercata and provides an easy and simple project. The Asset-Framework allows a developer or business user to input an asset data model into a .XLSX spreadsheet and easily create a working project. This project can then be altered by the developer to better suit the application's needs.
The Asset Framework Tool is available on Github: Asset Framework Github
For more information on STRATO Mercata, please visit: https://blockapps.net/products/strato-mercata/
In order to develop apps on Mercata, you must have a STRATO Mercata account.
Check out our VS Code extension! Signup for STRATO Mercata
Generated Project Description
Out of the box, the Asset Framework includes (but is not limited to) the following features:
- Deployment of your Dapp to a Private Dapp Realm
- Assets represented as Private Asset Shards
- User ownership and transfer Assets
- Basic JS Express API for basic Asset CRU methods
- React UI to display and enable basic Asset CRU flows
- Deployment of entire Dapp in Docker
- Reference Smart Contracts for common application development patterns, such as User Membership and Permissioning
Data Model Spreadsheet
The Asset Framework uses a spreadsheet to define the project's assets and configuration. See each section below to understands what each section of the sheet does.
Assets
This sheet defines the names, data fields, and possible relationships between the assets in your application.
Begin by listing out each asset type in your application - such as a "Product" and a "Machine". These will be the values in the first column, "Asset Name".
For each data field that an asset has, enter its name in a new row in the second column, "Asset Attribute". Match the asset attribute name with the corresponding asset type.
Next, define what type of data this attribute represents - a number, text, etc. Use the dropdown selection in the "Asset Attribute Type" to fill in this value. For "reference" types, this means that the attribute represents a foreign reference to another asset in the application. So enter the name of the referenced asset in the column to the right, "Reference to (for reference(s))". The "Reference to" column can be left blank for all non-reference type attributes.
Finally the remaining three columns - "Unit of Measure", "Description", and "Sample Value" are used entirely as utility columns to help you build out your data model. If you are unsure of what type your asset's attribute is, than enter in the data you know in these fields and think - "Which of the 6 data types matches this sample value"? These fields are useful to fill out to collaborate with other members of your team to develop the asset data model.
Note that the Framework already creates some default data fields on every asset, so those attributes should not be included in the data model:
appChainId
owner
ownerOrganization
ownerOrganizationalUnit
ownerCommonName
Project Overview
On the "Project Overview" sheet, there are three fields:
- Project Name
- This is the name given to the overall project. Primarily used in the generated UI and internal configuration files to identify the project.
- Project Description
- A brief description to give your project for its internal files.
- Project Creator
- The author/name of the person/organization creating the project. Used to identify the project with its creator in internal files.
Deployment Configuration
The deployment configuration should only be updated if you are a developer or technical user.
Below is an explanation of each value:
nodeUrl
- The URL of the Mercata node that your app will connect to
nodeLabel
- The label or name of the Mercata node - used to name the generated config file
openid_discovery_url
- The OAuth Provider configured with the Mercate Node you are connecting to, as well the OAuth provider to use when signing into the application
client_id
- A client ID in your OAuth provider realm to use for communicating with Mercata purely from the backend server
client_secret
- The secret associated with the client ID
Generating your Project
For a step-by-step guide to generating and running your app with the Asset Framework, refer to the Mercata App Quickstart Guide.
Additional Asset Framework Commands
-
yarn example <target/directory>
: given a directory, this will generate an example project included with the Asset Framework. This is mostly to see what and where the files for a given example project will look like. -
yarn template <filled-in-spreadsheet.xlsx> <target/directory>
: This will only generate the project source code, but will not install the project's dependencies. Most useful for development purposes. Note this command will not generate apackage.json
file. -
yarn read-xlsx <filled-in-spreadsheet.xlsx>
: this will generate the JS object that is used in the generation of the project from the data model spreadsheet. This is useful for development purposes so you can be sure the framework is interpreting your data model correctly.
Data Model JSON Representation
The Asset Framework converts the data model sheet into a JavaScript object that is referenced for the generation of your application.
Below is the format of that object:
Data Model Object Format
{
name: 'Planetarium',
description: 'Track the Ownership of planets',
creator: 'BlockApps',
organizations: [ 'Space UN', 'Interspace Government', 'United Moon Fronts' ],
assets: [
{
name: 'Planet',
attributes: [
{
attribute: 'Unique Planet ID',
field: 'unique_Planet_ID',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined
},
{
attribute: 'Planet Name',
field: 'planet_Name',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined
},
{
attribute: 'Planet Attributes',
field: 'planet_Attributes',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined
},
{
attribute: 'Acquisition Start Date',
field: 'acquisition_Start_Date',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'integer',
reference: undefined
},
{
attribute: 'Acquisition End Date',
field: 'acquisition_End_Date',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'integer',
reference: undefined
}
]
},
{
name: 'Biome',
attributes: [
{
attribute: 'Biome',
field: 'biome',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'reference',
reference: 'Planet'
},
{
attribute: 'Unique Biome ID',
field: 'unique_Biome_ID',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined
},
{
attribute: 'Name',
field: 'name',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined
},
{
attribute: 'Date discovered',
field: 'date_discovered',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'integer',
reference: undefined
}
]
},
{
name: 'Life',
attributes: [
{
attribute: 'Unique Lifeform ID',
field: 'unique_Lifeform_ID',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined
},
{
attribute: 'Lifeform common name',
field: 'lifeform_common_name',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined
},
{
attribute: 'Date Discovered',
field: 'date_Discovered',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'integer',
reference: undefined
},
{
attribute: 'Sustaining Biomes',
field: 'sustaining_Biomes',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'references',
reference: 'Biome'
}
]
}
]
}
We also reformulate into two more kinds of things for assets and references.
For assets we can just choose the asset based on the index. For example it would look like just
by doing dataModel.assets[0]
.
{
name: 'Planet',
attributes: [
{
attribute: 'Unique Planet ID',
field: 'unique_Planet_ID',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined,
referenceField: undefined
},
{
attribute: 'Planet Name',
field: 'planet_Name',
unitOfMeasure: undefined,
description: undefined,
sampleValue: undefined,
type: 'text',
reference: undefined,
referenceField: undefined
}
]
}
When we create contracts based on references, we reformulate the data model into
{
name: "Life Form",
reference: "Biome"
}