Quickstart Guide
This guide will provide a simple path to get up and running with Dragonchain no matter the size or scale of the project from startup to Enterprise.
Setup
A new Dragonchain business node can be created in 3 clicks in less than 10 minutes using the Dragonchain web console.
Before going further, please install the Dragonchain command line tool/shell (dctl) with:
yarn global add dctl
More in depth installation instructions can be found here.
Transactions
The core of a blockchain is a verifiably secure and immutable ledger. The most basic use case for a chain is ledgering data and state changes. As time goes on, each change is added on top of the last, forming a cryptographically secure chain of data transformations that can be easily traced from start to finish.
To follow along with this tutorial, you will need access keys to your business chain (L1).
Before your business chain will accept any transactions, you will need to create and register a transaction type
. To do so, run the transactionType create
command from the dctl
shell. For more detail, refer to the transaction types page. While transaction types are extensible and designed to support complex work flows, this example is of a simple ledger transaction called quickstart
.
$ dctl transactionType create quickstart
{
"status": 200,
"response": {
"success": true
},
"ok": true
}
Verify that the type has been created using dctl
:
$ dctl transactionType get quickstart
{
"status": 200,
"response": {
"version": "2",
"txn_type": "quickstart",
"custom_indexes": [],
"contract_id": "",
"active_since_block": "28147946"
},
"ok": true
}
Now that the chain has a transaction type, it will accept new transactions. Dragonchain business chains (L1) support indexing and searching transactions based on their transaction type. This helps provide logical separation between a business’ various data types.
Creating a transaction is as easy as providing a payload to dctl
:
$ dctl transaction create quickstart "Greetings from the quickstart guide"
Could not parse JSON for payload, sending raw data instead...
{
"status": 201,
"response": {
"transaction_id": "a4df336c-ba35-461c-ad8a-6e5d19049ddd"
},
"ok": true
}
To find the transaction, get it directly by id:
$ dctl transaction get a4df336c-ba35-461c-ad8a-6e5d19049ddd
{
"status": 200,
"response": {
"version": "2",
"dcrn": "Transaction::L1::FullTransaction",
"header": {
"txn_type": "quickstart",
"dc_id": "28GiivQE5m8a9oyvFD33JgwnBpgyZp2RxtTVFGjcRPVDJ",
"txn_id": "a4df336c-ba35-461c-ad8a-6e5d19049ddd",
"block_id": "28148014",
"timestamp": "1572978285",
"tag": "",
"invoker": ""
},
"payload": "Greetings from the quickstart guide",
"proof": {
"full": "RJ95GnsOmXVQIdIfjst/qldyFeFwT1Qh+vH2eJs3mnA=",
"stripped": "MEQCIFXCc1GNSfYJsE6rSiGeETDwUYpHEdAbBH4eEPzCc2kEAiARfGNj3G4gCQ9y9+jdRwT5uz6WVJWLMQZsQBSdOTbhyQ=="
}
},
"ok": true
}
Transactions can still be queried without the ID. By default, queries return transactions sorted by timestamp:
$ dctl transaction query quickstart "*"
{
"status": 200,
"response": {
"total": 1,
"results": [
{
"version": "2",
"dcrn": "Transaction::L1::FullTransaction",
"header": {
"txn_type": "quickstart",
"dc_id": "28GiivQE5m8a9oyvFD33JgwnBpgyZp2RxtTVFGjcRPVDJ",
"txn_id": "a4df336c-ba35-461c-ad8a-6e5d19049ddd",
"block_id": "28148014",
"timestamp": "1572978285",
"tag": "",
"invoker": ""
},
"payload": "Greetings from the quickstart guide",
"proof": {
"full": "RJ95GnsOmXVQIdIfjst/qldyFeFwT1Qh+vH2eJs3mnA=",
"stripped": "MEQCIFXCc1GNSfYJsE6rSiGeETDwUYpHEdAbBH4eEPzCc2kEAiARfGNj3G4gCQ9y9+jdRwT5uz6WVJWLMQZsQBSdOTbhyQ=="
}
}
]
},
"ok": true
}
Another way to index transactions is to use tags. When creating a transaction, tags are specified with --tag
:
$ dctl transaction create quickstart "This is my tag" --tag "my-tag"
Could not parse JSON for payload, sending raw data instead...
{
"status": 201,
"response": {
"transaction_id": "3c406d80-19c5-424e-999e-64a278e3fdca"
},
"ok": true
}
This looks exactly the same as creating a transaction without a tag, but can be queried by tag:
$ dctl transaction query quickstart "*"
{
"status": 200,
"response": {
"total": 2,
"results": [
...
]
},
"ok": true
}
$ dctl transaction query quickstart "@tag:my-tag"
{
"status": 200,
"response": {
"total": 1,
"results": [
{
"version": "2",
"dcrn": "Transaction::L1::FullTransaction",
"header": {
"txn_type": "quickstart",
"dc_id": "28GiivQE5m8a9oyvFD33JgwnBpgyZp2RxtTVFGjcRPVDJ",
"txn_id": "3c406d80-19c5-424e-999e-64a278e3fdca",
"block_id": "28148113",
"timestamp": "1572978782",
"tag": "my-tag",
"invoker": ""
},
"payload": "This is my tag",
"proof": {
"full": "2RPMG+GLULyNUgYS1wATl+kVeHgOIJGuMS2qgmGoxnk=",
"stripped": "MEQCIAy0aJXFExTQH4wKi1yBCJPa2T+hwfQy6WgeDzEgYauuAiABOwa914JlO/6goE/STLm/3LcF6wH1RxLAEQ4KfdRN6Q=="
}
}
]
},
"ok": true
}
Custom Indexes
A more advanced way to search for transactions on your business chain is to add custom search indexes when you create a transaction type. Any field in your transaction payload data structure can be indexed for efficient search. This capability can be used to provide advanced non-relational database capabilities directly within your business chain.
For more detail, please see the Creating Custom Search Indexes section of this guide.
Smart Contracts
Hello world
To create and execute a smart contract with custom business logic on the your business chain, three simple steps are necessary: (1) create a contract locally (including a fully-featured test environment), (2) build the image, (3) and run it!
To see how easy this is, copy and paste the following 3 commands to your console:
dctl contract init --language node --dir my-contract
docker build ./my-contract/src/ -t my-contract
dctl contract test --test-directory ./my-contract/test/ --payload "hello world" my-contract:latest
Once completed, the contract will output:
STDERR: hello world
STDERR: Call Count: 1
{"myCounter":1}
These commands create a contract locally (including a fully-featured test environment), build the image, and run it! That’s all it takes to start building a smart contract on Dragonchain!
A Little More About Smart Contracts
Unlike other blockchains where developers have to write smart contracts in specific languages so that the code can compile on the blockchain’s virtual machine, the Dragonchain Platform makes use of Docker to deploy independently scalable smart contracts in any programming language they desire (limited only by Docker). Developers may use JSON for input and output, test locally, deploy frequently, and even update or delete existing smart contracts. This model offers unprecedented flexibility in blockchain development.
To get started building a smart contract, navigate to an empty directory and run the following:
$ dctl contract init --language node
Creating new local contract environment...
No directory specified. Write test env files to current directory? [Y/N] y
Writing: test/.env
Cloning into 'tmp'...
Done
Running contract init
sets up the environment to develop a smart contract. Contract init
supports several languages, but this example uses the nodejs
language. The init
command also creates a few test files with sample tests to help you start your development effort.
Replace the code in handler.js
with the following:
module.exports = async function (fullTransaction) {
if (!fullTransaction || !fullTransaction.payload || !fullTransaction.payload.name) {
return { error: "I can't say hi if I don't know your name!" };
}
return { greeting: `Hello ${fullTransaction.payload.name}!`, OUTPUT_TO_HEAP: false}
}
Use the command docker build . -t my-contract
to build the image. The image needs to be pushed to a remotely accessible docker repository before the contract can be deployed. Alternately, dctl
can be used to test the smart contract locally with the following:
$ dctl contract test --test-directory ./my-contract/test/ --payload '{"name": "banana"}' my-contract:latest
{"greeting":"Hello banana!", "OUTPUT_TO_HEAP": false}
dctl
can also be used to deploy the contract my-contract
with the following command:
$ dctl contract create my-contract my-contract:latest node index.js
{
"status": 202,
"response": {
"dcrn": "SmartContract::L1::AtRest",
"version": "1",
"txn_type": "my-contract",
"id": "b7165579-c9bb-46f7-8853-ae1c1939883f",
"status": {
"state": "Pending",
"msg": "Contract creating",
"timestamp": "2019-11-05 21:25:09.806836"
},
"image": "my-contract:latest",
"auth_key_id": null,
"image_digest": null,
"cmd": "node",
"args": [
"index.js"
],
"env": null,
"existing_secrets": null,
"cron": null,
"seconds": null,
"execution_order": "parallel"
},
"ok": true
}
Once a contract is deployed, you need to create a transaction type that can be used to invoke the contract:
$ dctl transaction create my-contract '{ "payload": { "name": "banana" } }'
{
"status": 201,
"response": {
"transaction_id": "8f3faf1d-3a18-4f5f-bc3e-36561643d8f1"
},
"ok": true
}
$ dctl transaction query my-contract "@invoker:8f3faf1d-3a18-4f5f-bc3e-36561643d8f1"
{
"status": 200,
"response": {
"total": 1,
"results": [
{
"version": "2",
"dcrn": "Transaction::L1::FullTransaction",
"header": {
"txn_type": "my-contract",
"dc_id": "28GiivQE5m8a9oyvFD33JgwnBpgyZp2RxtTVFGjcRPVDJ",
"txn_id": "6d9e845c-125a-48cf-925d-af6c61c0a71c",
"block_id": "28150206",
"timestamp": "1572989248",
"tag": "",
"invoker": "8f3faf1d-3a18-4f5f-bc3e-36561643d8f1"
},
"payload": {
"greeting":"Hello banana!"
},
"proof": {
"full": "kXLmBlsKOh+vUTVH5F8lA3R4JAJBXTiohWLPIUpHNTc=",
"stripped": "MEUCIQCZmruFoFy0UJcbtj3/wCbjDK0MUtcXeemPPq7j8tycPgIgOcGHJosVWWBPacWIxuNsEydYK8qPpck9rpSOMlvIjes="
}
}
]
},
"ok": true
}
Once a contract deploys successfully, it can be invoked.
And that’s all you need to get started ledgering transactions and create smart contracts on your business chain!