JavaScript
Factom "Hello World" in JavaScript
In this tutorial we will be using the factom.js library to write a simple Node.js application using Factom. Along the way we will learn the important concepts of Factom and all the fundamental operations to interact with the blockchain.
Requirements
Node.js 8+
npm (or yarn)
Docker (if using Factom Dev Stack to run the local Factom blockchain)
Setup
Setting up a local Factom blockchain
For this tutorial we will be running our own local Factom blockchain to make our development experience smoother:
We have a faster block time (few seconds instead of 10 minutes on mainnet/testnet).
We have immediate access to Factoids to interact with the blockchain (for free).
We avoid potential availability/connectivity/latency inconveniences.
In this tutorial we'll be using the simplest solution, Factom Dev Stack (FDS), that only requires you to have Docker installed. There exist other ways to set up a developer sandbox which can you can lookup here.
Install Factom Dev Stack globally on your machine:
You may need to use sudo
in font of the command above to install FDS globally.
And then start FDS:
The first time you launch FDS it will download the Docker images of factomd
and factom-walletd
which may take some time.
Launching FDS without extra argument like above creates an ephemeral blockchain that will be cleaned up once FDS is stopped. See here for more info.
Once FDS is started the control panel of your running Factom node is available on port 8090
, you can visualize it by opening http://localhost:8090/ in a browser. The control panel can be used to see the state of your blockchain and also as an explorer. Find more detailed info here about the control panel if you are interested.
You now have an instance of factomd
(Factom daemon) and factom-walletd
(wallet daemon) running that you can interact with. By default factomd
exposes a JSON-RPC API on port 8088
and factom-walletd
exposes a JSON-RPC API on port 8089
. Those are the set of APIs we are going to use to interact with our Factom blockchain.
Setting up our project
Let's set up a basic Node.js project with factom.js as a dependency:
Factom JS development 101
The complete technical doc of factom.js is available online at https://factomjs.luciap.ca/
Instantiating FactomCli
A FacomCli
instance allows you to interact easily with both factomd
and factom-walletd
.
Without any argument passed to the constructor the instance will connect by default to local instances of factomd
and factomd-walletd
, which is what we want in this tutorial. If you wanted to specify the endpoints (to connect to a mainnet node for instance) you can pass options to the constructor:
All the options available are described here: https://factomjs.luciap.ca/#connectionoptions
In the rest of the tutorial we will directly reference the cli
variable without re-defining it every time.
Dual token system, addresses and balances
Factom has a dual token system:
Factoid (FCT) is the token to transfer value. It's possible to send and receive Factoids and they are traded on multiple crypto-currency exchanges with a fluctuating value relative to USD or BTC.
Entry Credit (EC) is the token to insert data in the Factom blockchain. The only way to create Entry Credits is to burn Factoids and ECs cannot be transferred once created. They can only be used (burned) to pay for writing data. The conversion rate from FCT to EC is always adjusted such that 1 EC costs ~0.001 USD at all time.
Because there are two tokens there are two sets of addresses. Addresses have a public and private part, and the prefix (2 first letters) is different for each type. Here's a summary:
When starting a new local network the genesis block will fund the address FA2jK2HcLnRdS94dEcU27rF3meoJfpUcZPSinpb7AwQvPRY6RL1Q
for which we luckily know the corresponding private address, Fs3E9gV6DXsYzf7Fqx1fVBQPQXV695eP3k5XbmHEZVRLkMdD9qCK
, so we will be able to use those funds. Let's check the balance of this address:
It should return a value of 2000000000000
which is the amount in factoshis. So we are starting we 20,000 FCT on this address.
To get other addresses to work with we have two options:
Generally it is a better idea to derive the addresses from a seed as it allows you to backup that seed and restore all the addresses from it later if needed.
Similarly to the method walletdApi
you have access to a method factomdApi
that allows you to make calls directly against factomd API.
Making transactions
Sending Factoids
Let's see how to transfer some of those FCT to another address. Factom.js has a convenient method createFactoidTransaction
for SISO (Single Input Single Output) transactions:
The amount is in factoshis (and not factoids).
As the input of the transaction we use the private part of the source address. If the address was imported in the wallet we could have use the public address and the library would have fetched the private counterpart from the wallet seamlessly.
You can search for the transaction id (after the next block is produced) in your node control panel and should see something like this:
Converting FCT to EC
To insert chains and entries in the Factom blockchain we will need Entry Credits. ECs can be obtained by burning Factoids. We can use the createEntryCreditPurchaseTransaction
method for that:
Note that the amount here is the number of Entry Credits to convert to. The library will compute for you how much factoshis it will cost.
Complex transactions
In the previous sections we used the helper methods createFactoidTransaction
andcreateEntryCreditPurchaseTransaction
to craft valid transactions for us (including fees etc). The library allows you to craft yourself complex transactions if you wanted to. Examples can be found here.
Creating chains and entries
Now that we have some Entry Credits we can write data in the blockchain. In Factom we create chains which can then contain entries. Entries can contain any arbitrary data. The structure of chains allows to logically organize your data. Some important facts to know about chains and entries:
One entry is composed of a list of external IDs and a content. Any of those can be empty.
One entry can contain up to 10kb of data.
The cost of writing an entry is 1 EC/kb (so between 1 EC and 10 EC).
The cost of creating a chain is 10 EC + the cost the first entry (so between 11 EC and 20 EC).
A chain is simply defined by its first entry. The chain ID is derived from the external IDs of that first entry.
Remember that anybody can read all the entries of any chain. Also anybody can add an entry to any chain. Chains are not secret or private. If you want to learn more about some patterns to deal with this you can read Design patterns on Factom.
Creating our first chain
Be aware that the default string encoding of the external ids and the content is hex
. You can specify an encoding as a second argument or pass directly an instance of Buffer
.
Search for the chain ID in the control panel (after the next block has been produced):
Adding an entry to an existing chain
Reading chains and entries
Reading entries
Now that we have inserted data into Factom we want to be able to read that data from the blockchain. You can query an entry directly by its entry hash:
The external IDs and content of the entry are returned as Buffer
and it is up to your application to interpret/decode that raw data.
The entry returned by getEntry
does not contain a timestamp and a block context (details about which block the entry was included in). If you need that data you can use getEntryWithBlockContext
instead, but be aware that this method is more expensive as it makes 3 API calls.
Reading chains
If we want to retrieve all the entries of a given chain we can simply do so:
This method will rewind the whole chain and retrieve all its entries. However if the chain is long this is not a good approach. Another method allows you to control the rewind of the chain and process the entries one by one:
The second argument is a predicate that allows you to halt the loop. If that predicate never evaluates to false the rewind will stop once the whole chain has been processed.
Let's build a factomizer
We now have all the components we need write our first Factom application. This will be a simple "factomizer": an app that allows to store the hash of a file on Factom and then later verify the integrity of the file against the data stored in the entry.
This basic implementation of a factomizer is not to be considered suitable for real world usage. For the sake of simplicity we didn't address some flaws, the biggest one being the authentication of the data recorded (remember that anyone could write in your chain).
Factomizing operation
Our main function has 3 steps:
We build a new
Chain
object that contains information about the file we want to secure on Factom.We buy enough entry credits on the fly to pay for writing that data.
We add the chain to Factom.
Here we are creating a new a new chain per file. Another approach could be to create one chain where you will append new entries for all your factomized files. We put some metadata in the external ids (filename, timestamp) and the SHA512 of the file in the content of the entry. We also added 'simple-factomized' in the first external ID as a simple marker for easier identification of the nature of the entry,.
We have a function to buy entry credits for the specific amount needed for the sake of re-using what we learned previously. But in practice you will often use an EC address that already have enough ECs and that is regularly topped up to stay with a large positive balance.
Everything together gives us our simple factomizer:
Usage:
Verification operation
Now that we have secured a document in the blockchain we need an operation to be able to verify at a later time the integrity of that document. The steps are straightforward:
Compute the hash of the file we want to check the integrity.
Fetch the hash recorded in the corresponding Factom entry.
Compare both hashes.
Everything together:
Usage:
Complete source code
The complete source code of this simple factomizer is available online at https://github.com/PaulBernier/simple-factomizer
Conclusion
You should know have all the fundamentals to start building your own application on top of Factom. To go further you can explore the complete documentation of factom.js and read the article Design patterns on Factom. Have fun!
Last updated