Tutorials

Creating your first vAtom
Ethereum enabled vAtom
Writing your first Android app
Writing your first iOS app

Creating your first vAtom

Overview

The BLOCKv Platform gives vAtom publishers and developers the ability to choose whether or not to leverage a blockchain for each of the vAtom templates they create. Publishers may wish to keep certain vAtoms off-chain for vAtoms which have no inherent value or scarcity and are not intended for use outside of the BLOCKv platform. For vAtoms that are intended to be used on-chain (and therefore viewable in external wallets), publishers may choose to enable this functionality in their templates.

The platform also allows publishers to choose which blockchain network to leverage (Bitcoin, Ethereum, EOS, etc.), giving them the freedom to choose a network that best meets their requirements, including performance targets and processing costs.

In this tutorial, we are going to learn how to create a template, template variation, and emit an off-chain vAtom that can be held in your wallet or transferred to another user.

To execute this tutorial you need an App-Id, pub_fqdn, and a valid BLOCKv user with publisher rights. To request these credentials click here.

Steps 2 & 3 in this tutorial are completely optional. You can safely skip them.

1. Login with your user account

API Reference: Login API

Login using email

{
	"token" : "john.doe@example.com",
	"token_type" : "email",
	"auth_data" : {
		"password": "secret"	
	}
}

From the response payload, save access_token & pub_fqdn for future use. access_token value is sent as an Authorization HTTP Header. See Getting Started for details.

Successful Login Response

{
    "status": "success",
    "error": 0,
    "message": "",
    "payload": {
        "user": {
            "id": "6e0...",
            "meta": {
                "when_created": "2018-02-26T20:47:31Z",
                "when_modified": "2018-03-12T17:43:49Z",
                "data_type": "blockv::user"
            },
            "properties": {
                "first_name": "John",
                "last_name": "Doe",
                "name_public": false,
                "password": "",
                "avatar_uri": "http://example.com/mypic.jpg",
                "avatar_public": false,
                "birthday": "1970-01-01",
                "guest_id": "",
                "nonpush_notification": false,
                "language": "en"
            },
            "system_properties": {
                "pub_fqdn": "blockv.demo",
                "is_admin": true,
                "activated": false,
                "last_login": "2018-03-12T17:43:49Z",
                "is_merchant": false
            }
        },
        "asset_provider": [
            {
                "name": "blockv",
                "type": "Cloudfront",
                "uri": "https://cdndev.blockv.net",
                "descriptor": {
                    "Policy": "eyJTdGF0ZW...",
                    "Signature": "gSMwEjr7...",
                    "Key-Pair-Id": "A..."
                }
            }
        ],
        "access_token": {
            "token": "ey...",
            "token_type": "Bearer",
            "expires_in": 5000
        },
        "refresh_token": {
            "token": "ey...",
            "token_type": "Bearer",
            "expires_in": 43200
        }
    }
}

2. Get all public templates (Optional)

There are several types of public Templates. Most commonly used templates are:

  • 3D Object (vatomic.templates::3D-Object::v1)
  • Plain Image (vatomic.templates::Image::v1)
  • Media Player (vatomic.templates::MediaPlayer::v1)
  • Web View (vatomic.templates::WebView::v1)

Each of these templates (and many others) are already supported by the SDK for iOS and Android. Nothing is stopping you from creating your own Templates that are unique to your own custom viewer, but using an existing viewer will help you get started.

API Reference: Get Templates API

Get All Public Templates

GET	/v1/templates?public=true&page[size]=50&fields=name

3. Retrieve an existing Template (Optional)

Let's see what an existing (image) template looks like. Retrieve an pre-existing Image Template (vatomic.templates::Image::v1).

API Reference: Get Template API

Get Image Template

GET /v1/templates/vatomic.templates::Image::v1

Image Template Details

{
    "payload": {
        "name": "vatomic.templates::Image::v1",
        "public": true,
        "meta": {
            "created_by": "557d18d9-259a-4c44-a088-a9601a05ab22",
            "when_created": "2017-03-29T20:41:52Z",
            "modified_by": "557d18d9-259a-4c44-a088-a9601a05ab22",
            "when_modified": "2017-03-29T20:41:52Z",
            "data_type": "vAtom::vAtomTemplateType"
        },
        "properties": {
            "publisher_fqdn": "vatomic",
            "template": {
                "vAtom::vAtomType": {
                    "parent_id": ".",
                    "publisher_fqdn": "vatomic",
                    "root_type": "vAtom::vAtomType",
                    "owner": "557d18d9-259a-4c44-a088-a9601a05ab22",
                    "author": "557d18d9-259a-4c44-a088-a9601a05ab22",
                    "template": "vatomic.templates::Image::v1",
                    "template_variation": "",
                    "notify_msg": "",
                    "title": "Image",
                    "description": "This is a Template for a single image vAtom",
                    "disabled": false,
                    "category": "",
                    "tags": [],
                    "transferable": true,
                    "acquirable": false,
                    "tradeable": false,
                    "transferred_by": "",
                    "cloned_from": "",
                    "cloning_score": 0,
                    "in_contract": false,
                    "redeemable": false,
                    "in_contract_with": "",
                    "commerce": {
                        "pricing": {
                            "pricingType": "",
                            "value": {
                                "currency": "",
                                "price": "",
                                "valid_from": "",
                                "valid_through": "",
                                "vat_included": false
                            }
                        }
                    },
                    "states": [
                        {
                            "name": "Activated",
                            "value": {
                                "type": "boolean",
                                "value": "true"
                            },
                            "on_state_change": {
                                "reactor": ""
                            }
                        }
                    ],
                    "resources": [
                        {
                            "name": "ActivatedImage",
                            "resourceType": "ResourceType::Image::PNG",
                            "value": {
                                "resourceValueType": "ResourceValueType::URI",
                                "value": "https://cdn.blockv.io/vatomic.templates/vatomic.templates::Image::v1/image_icon.png"
                            }
                        }
                    ],
                    "visibility": {
                        "type": "owner",
                        "value": "*"
                    },
                    "num_direct_clones": 0,
                    "geo_pos": {
                        "$reql_type$": "GEOMETRY",
                        "coordinates": [
                            0,
                            0
                        ],
                        "type": "Point"
                    },
                    "dropped": false
                },
                "private": {},
                "in_sync": false,
                "is_syncing": false,
                "version": ""
            },
            "cloneable": false,
            "unpublished": false
        }
    }
}

4. Create a new Template

We are going to create a new Template just like the one above in our publisher workspace.

Read Template basics for more information on Templates and Template Variation.

Attribute template is a unique id used to reference the template. It always starts with your pub_fqdn, in this example it is blockv.demo.

The ActivatedImage and CardImage resources specified below are used by the viewer to display the vAtom. The ActivatedImage is shown in the inventory view and the CardImage is displayed when the vAtom is "opened". As an example, imagine that the CardImage is a Rare Pepe image. The viewer has essentially become a Rare Pepe wallet!

API Reference: Create Template API

Create an Image Template

{
    "template": "blockv.demo::demo::Image::v1",
    "public": false,
    "cloneable": false,
    "unpublished": true,
    "vatom": {
        "vAtom::vAtomType": {
            "root_type": "vAtom::vAtomType",
            "description": "This is a demo Image Template",
            "title": "Image",
            "redeemable": true,
          	"states": [
              	{
                  	"name": "Activated",
                  	"value": {
                      "type": "boolean",
                      "value": "true"
                  	}
              	}
        	],
          	"resources": [
            	{
                    "name": "ActivatedImage",
                    "resourceType": "ResourceType::Image::PNG",
                    "value": {
                        "resourceValueType": "ResourceValueType::URI",
                        "value": ""
                    }
            	},
            	{
                    "name": "CardImage",
                    "resourceType": "ResourceType::Image::JPEG",
                    "value": {
                        "resourceValueType": "ResourceValueType::URI",
                        "value": ""
                    }
                }
            ]
        },
        "private": {}
    }
}

Template blockv.demo::demo::Image::v1 created

{
    "payload": {
        "success_message": "created Template successfully"
    }
}

At this point, you can run the Get Template call with this newly registered name to verify.

Get Demo Image Template

GET /v1/templates/blockv.demo::demo::Image::v1

You should see something like -

Get Template

{
    "payload": {
        "name": "blockv.demo::demo::Image::v1",
        "public": false,
        "meta": {
            "created_by": "6e0ed730-26ff-45c0-b558-0df979d754ca",
            "when_created": "2018-03-12T19:10:24Z",
            "modified_by": "6e0ed730-26ff-45c0-b558-0df979d754ca",
            "when_modified": "2018-03-12T19:10:24Z",
            "data_type": "vAtom::vAtomTemplateType",
            "in_sync": false,
            "when_synced": "",
            "is_syncing": false
        },
        "properties": {
            "publisher_fqdn": "blockv",
            "template": {
                "vAtom::vAtomType": {
                    "parent_id": ".",
                    "publisher_fqdn": "blockv",
                    "root_type": "vAtom::vAtomType",
                    "owner": "6e0ed730-26ff-45c0-b558-0df979d754ca",
                    "author": "6e0ed730-26ff-45c0-b558-0df979d754ca",
                    "template": "blockv.demo::demo::Image::v1",
                    "template_variation": "",
                    "notify_msg": "",
                    "title": "Image",
                    "description": "This is a demo Image Template",
                    "disabled": false,
                    "category": "",
                    "tags": [],
                    "transferable": true,
                    "acquirable": false,
                    "tradeable": false,
                    "transferred_by": "",
                    "cloned_from": "",
                    "cloning_score": 0,
                    "in_contract": false,
                    "redeemable": true,
                    "in_contract_with": "",
                    "commerce": {
                        "pricing": {
                            "pricingType": "",
                            "value": {
                                "currency": "",
                                "price": "",
                                "valid_from": "",
                                "valid_through": "",
                                "vat_included": false
                            }
                        }
                    },
                    "states": [
                        {
                            "name": "Activated",
                            "value": {
                                "type": "boolean",
                                "value": "true"
                            },
                            "on_state_change": {
                                "reactor": ""
                            }
                        }
                    ],
                    "resources": [
                        {
                            "name": "ActivatedImage",
                            "resourceType": "ResourceType::Image::PNG",
                            "value": {
                                "resourceValueType": "",
                                "value": ""
                            }
                        },
                        {
                            "name": "CardImage",
                            "resourceType": "ResourceType::Image::JPEG",
                            "value": {
                                "resourceValueType": "",
                                "value": ""
                            }
                        }
                    ],
                    "visibility": {
                        "type": "owner",
                        "value": "*"
                    },
                    "num_direct_clones": 0,
                    "geo_pos": {
                        "$reql_type$": "GEOMETRY",
                        "coordinates": [
                            0,
                            0
                        ],
                        "type": "Point"
                    },
                    "dropped": false
                },
                "private": {},
                "in_sync": false,
                "is_syncing": false,
                "version": ""
            },
            "cloneable": false,
            "unpublished": true
        }
    }
}

5. Register the Faces for your Template

This step informs the viewer (iOS only - set under constraints) to use a native image renderer to display the ActivatedImage.

Read Face basics for more information on Resource Types and View Modes.

API Reference: Register Face API

Set ActivatedImage as a native image

{
    "template": "blockv.demo::demo::Image::v1",
    "display_url": "native://image",
    "package_url": "native://image",
    "constraints": {
        "bluetooth_le": false,
        "contact_list": false,
        "gps": false,
        "view_mode": "icon",
        "platform": "generic",
        "three_d": false,
        "quality": "high"
    },
    "resources": [ 
        "ActivatedImage" 
    ]
}

Set CardImage as a native image

{
    "template": "blockv.demo::demo::Image::v1",
    "display_url": "native://image",
    "package_url": "native://image",
    "constraints": {
        "bluetooth_le": false,
        "contact_list": false,
        "gps": false,
        "view_mode": "card",
        "platform": "generic",
        "three_d": false,
        "quality": "high"
    },
    "resources": [
        "CardImage"
    ]
}

Successful Face Registration

{
    "payload": {
        "successMessage": "Registered face for template=blockv.demo::demo::Image::v1, id=7d2aaa60-a686-4013-b269-989376d5fee1"
    }
}

6. Register the Transfer Action for your Template.

The platform provides many action options to the developers. For this guide, we will register transfer action with the template. This action allows vAtom to be transferred to another user.

name of the action SHOULD always start with the template name. In this case, it is blockv.demo::demo::Image::v1.

API Reference: Register Action API

Register Transfer Action

{
    "name": "blockv.demo::demo::Image::v1::Action::Transfer",
    "reactor": "blockv://v1/Transfer",
    "wait": true,
    "rollback": false,
    "abort_on_pre_error": true,
    "abort_on_post_error": false,
    "abort_on_main_error": true,
    "timeout": 10000,
    "guest_user": true,
    "config": {
        "auto_create_landing_page": "http://viewer.blockv.io/#",
        "auto_create_mode": "claim",
        "auto_create_non_existing_recipient": true
    },
    "action_notification": {
        "on": true,
        "msg": "You received a vAtom",
        "custom": {}
    }
}

Successful Action Registration

{
    "payload": {
        "successMessage": "Registered action: name=blockv.demo::demo::Image::v1::Action::Transfer"
    }
}

7. Create a Template Variation

In this step, we will further refine the template by setting values for resources, for example ActivatedImage and CardImage.

API Reference: Create Variation API

Create Variation

{
  "template": "blockv.demo::demo::Image::v1",
  "template_variation": "blockv.demo::demo::Image::v1::tutorial::v1",
  "public": false,
  "cloneable": false,
  "max_clones_per_instance": 0,
  "max_clones_total": 0,
  "max_num": 100,
  "per_clone_gain": 1,
  "auto_create_on_acquire": false,
  "unpublished": true,
  "vatom": {
    "vAtom::vAtomType": {
      "transferable": true,
      "acquirable": false,
      "redeemable": false,
      "title": "Tutorial",
      "category": "education",
      "description": "This is just a demo",
      "resources": [
        {
          "name": "ActivatedImage",
          "resourceType": "ResourceType::Image::PNG",
          "value": {
            "resourceValueType": "ResourceValueType::URI",
            "value": "https://demo.blockv.io/developer-portal/tutorial-first-vatom/vee.png"
          }
        },
        {
          "name": "CardImage",
          "resourceType": "ResourceType::Image::JPEG",
          "value": {
            "resourceValueType": "ResourceValueType::URI",
            "value": "https://demo.blockv.io/developer-portal/tutorial-first-vatom/popup-card.jpg"
          }
        }
      ],
      "visibility": {
        "type": "owner",
        "value": "*"
      }
    },
    "private": {}
  }
}

Sample Response

{
    "payload": {
        "success_message": "created TemplateVariation successfully"
    }
}

8. Emit a vAtom

Once the Template Variation is created, you can now emit a vAtom:

Note that both the template and variation are unpublished. There is a limit on total number of vatoms (10 vatoms) that can be emitted.

API Reference: Emit vAtom API

Emit the demo vAtom

{
  "template_variation": "blockv.demo::demo::Image::v1::tutorial::v1",
  "num": 1
}

Emitted vAtom with Id

{
    "payload": {
        "num_created": 1,
        "num_errors": 0,
        "ids": [
            "7c45926a-5a54-4632-b1bb-9f2bbc65ffbc"
        ]
    }
}

Congratulations! You have just created a vAtom. You can find this vatom in your wallet (next step).

9. Listing vAtoms in your wallet

As a user you can easily get an inventory of your vAtoms which allows you to easily build a wallet of virtual goods or tokens.

API Reference: Get Inventory API

Get Inventory

{
    "parent_id": ".",
    "limit": 10,
    "page": 0
}

My Wallet

{
    "payload": {
        "vatoms": [
            {
                "id": "7c45926a-5a54-4632-b1bb-9f2bbc65ffbc",
                "in_sync": false,
                "is_syncing": false,
                "private": {},
                "unpublished": true,
                "vAtom::vAtomType": {
                    "acquirable": false,
                    "author": "6e0ed730-26ff-45c0-b558-0df979d754ca",
                    "category": "education",
                    "cloned_from": "",
                    "cloning_score": 0,
                    "commerce": {
                        "pricing": {
                            "pricingType": "",
                            "value": {
                                "currency": "",
                                "price": "",
                                "valid_from": "",
                                "valid_through": "",
                                "vat_included": false
                            }
                        }
                    },
                    "description": "This is just a demo",
                    "disabled": false,
                    "dropped": false,
                    "geo_pos": {
                        "$reql_type$": "GEOMETRY",
                        "coordinates": [
                            0,
                            0
                        ],
                        "type": "Point"
                    },
                    "in_contract": false,
                    "in_contract_with": "",
                    "notify_msg": "",
                    "num_direct_clones": 0,
                    "owner": "6e0ed730-26ff-45c0-b558-0df979d754ca",
                    "parent_id": ".",
                    "publisher_fqdn": "blockv",
                    "redeemable": false,
                    "resources": [
                        {
                            "name": "ActivatedImage",
                            "resourceType": "",
                            "value": {
                                "resourceValueType": "",
                                "value": "https://cdn.blockv.io/blockv.templates/publisher_fqdn/Template_Name/v1/Variation_Name/v1/icon.png"
                            }
                        },
                        {
                            "name": "CardImage",
                            "resourceType": "",
                            "value": {
                                "resourceValueType": "",
                                "value": "https://cdn.blockv.io/blockv.templates/publisher_fqdn/Template_Name/v1/Variation_Name/v1/example.jpg"
                            }
                        }
                    ],
                    "root_type": "vAtom::vAtomType",
                    "states": [
                        {
                            "name": "Activated",
                            "on_state_change": {
                                "reactor": ""
                            },
                            "value": {
                                "type": "boolean",
                                "value": "true"
                            }
                        }
                    ],
                    "tags": [],
                    "template": "blockv.demo::demo::Image::v1",
                    "template_variation": "blockv.demo::demo::Image::v1::tutorial::v1",
                    "title": "Tutorial",
                    "tradeable": false,
                    "transferable": true,
                    "transferred_by": "",
                    "visibility": {
                        "type": "owner",
                        "value": "*"
                    }
                },
                "version": "v1::vAtomType",
                "when_created": "2018-03-13T19:32:45Z",
                "when_modified": "2018-03-13T19:32:45Z"
            }
        ],
        "faces": [
            {
                "id": "7d2aaa60-a686-4013-b269-989376d5fee1",
                "template": "blockv.demo::demo::Image::v1",
                "meta": {
                    "created_by": "Appdriver Backend",
                    "when_created": "2018-03-12T22:18:19Z",
                    "modified_by": "",
                    "when_modified": "2018-03-12T22:18:19Z",
                    "data_type": "v1::FaceType",
                    "in_sync": false,
                    "when_synced": "",
                    "is_syncing": false
                },
                "properties": {
                    "display_url": "native://image",
                    "package_url": "native://image",
                    "constraints": {
                        "bluetooth_le": false,
                        "contact_list": false,
                        "gps": false,
                        "three_d": false,
                        "view_mode": "icon",
                        "platform": "generic",
                        "quality": "high"
                    },
                    "resources": [
                        "ActivatedImage"
                    ]
                }
            }
        ],
        "actions": [
            {
                "name": "blockv.demo::demo::Image::v1::Action::Transfer",
                "meta": {
                    "created_by": "Appdriver Backend",
                    "when_created": "2018-03-12T22:16:48Z",
                    "modified_by": "",
                    "when_modified": "2018-03-12T22:16:48Z",
                    "data_type": "v1::ActionType",
                    "in_sync": false,
                    "when_synced": "",
                    "is_syncing": false
                },
                "properties": {
                    "name": "blockv.demo::demo::Image::v1::Action::Transfer",
                    "reactor": "blockv://v1/Transfer",
                    "wait": true,
                    "rollback": false,
                    "abort_on_pre_error": true,
                    "abort_on_post_error": false,
                    "abort_on_main_error": true,
                    "timeout": 10000,
                    "guest_user": true,
                    "state_impact": [],
                    "policy": {
                        "pre": [],
                        "rule": "",
                        "post": []
                    },
                    "params": {
                        "input": [],
                        "output": []
                    },
                    "config": {
                        "auto_create_landing_page": "http://viewer.blockv.io/#",
                        "auto_create_mode": "claim",
                        "auto_create_non_existing_recipient": true
                    },
                    "limit_per_user": 0,
                    "action_notification": {
                        "on": true,
                        "msg": "You received a vAtom",
                        "custom": {}
                    }
                }
            }
        ]
    }
}

Transferring vAtoms (Optional)

You can now simply invoke the Transfer action to send the vAtom to someone based on their phone number or email address.

API Reference: Perform Actions API

Conclusion

Being able to transfer virtual goods (which can include tokens etc) on the blockchain using a phone number or email address greatly simplifies a highly complex process — making the blockchain networks much more accessible to developers. When transferring a vAtom on BlockV, the vAtom is simultaneously transferred from the publisher’s blockchain wallet to the target’s blockchain wallet.

Next Steps

As an excercise, take the existing template add additional actions drop and acquire. Once these actions are available at the template level, you should be able to drop an atom at a geo-location for others to pickup (acquire).

©2020 BLOCKv
Info