- Notifications
You must be signed in to change notification settings - Fork0
Object database implementation for the Factom protocol
License
DBGrow/factom-objectdb
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
A blockchain object database implemented in NodeJS, built on Factom - all for a fraction of the cost of competitors.
This database enables basic immutable Create, Read, and Update database operations for JSON objects stored on the Factom blockchain, and features a familiar MongoDB inspired update syntax.
You can run factom-objectdb as a standalone operational database daemon(HTTP API), or use it as a library in NodeJS (see examples below)
Command Line:
git clone https://github.com/DBGrow/factom-objectdb.git
or
Using NPM:
npm -i factom-objectdb
or
Inpackage.json:
"dependencies": {"factom-objectdb":"0.0.3",}
To run factom-objectdb standalone as a daemon and API host from the command line:
cd factom-objectdbnpm startThe objectdb HTTP API will be available at port 3000 on your localhost
You can use theconfig.json file in the root project directory to control how the daemon runs:
{"apiport":3000,"es":"Es3k4L7La1g7CY5z....."}Simple Initialization:
const{FactomObjectDB}=require('factom-objectdb');constdb=newFactomObjectDB({db_id:'factomdbtest:0.0.1',//the ID of your databaseec_address:'Es3k4L7La1g7CY5zVLer21H3JFkXgCBCBx8eSM2q9hLbevbuoL6a',//Public or private EC address});
All configuration options:
constdb=newFactomObjectDB({db_id:'factomdbtest:0.0.1',//the ID of your databaseec_address:'Es3k4L7La1g7CY5zVLer21H3JFkXgCBCBx8eSM2q9hLbevbuoL6a',//Public or private EC addressfactom:{factomd:{host:'52.202.51.228',port:8088},walletd:{host:'52.202.51.228',port:8089},user:'username',// RPC basic authenticationpassword:'pwd',rejectUnauthorized:true,// Set to false to allow connection to a node with a self-signed certificateretry:{retries:4,factor:2,minTimeout:500,maxTimeout:2000}}});
Lets say we have an object we want to store, a person in a database:
constjoe={_id:'134e366520a6f93265eb',name:'Joe Testerson',age:30,best_friends:[]};
We want to store the object under unique ID134e366520a6f93265eb (joe._id)
Saving the object permanently in Factom is as easy as:
//save the initial object to Factom!//using async/awaitconststoredObject=awaitdb.commitObject('134e366520a6f93265eb',joe);//or using promisesdb.commitObject(joe._id,joe).then(function(storedObject){}).catch(function(err){throwerr;});
It is important to note that creation of and updates to objects take up until the next block to be reflected (up to 10 Minutes).
Get Joe's object using his id:5ad28b9d18c35e2b4c000001
constjoe=awaitdb.getObject("134e366520a6f93265eb");
Retrieved Object:
{"_id":"134e366520a6f93265eb","name":"Joe Testerson","age":25,"best_friends":[]}
This library uses aMongoDB inspired update syntax.
Currently, these operators are supported:
$set: Set the value of a key in the object$unset: Delete the key from an object$rename: Rename the key of an object$inc: Increase the value of the key of an object by an amount$mul: Multiply the value of the key by an number$push: Add a value to the end of an array$pop: Remove a value from the end of an array
Updates to Factom objects are subject to the object's Field and Object rules. Updates that do not meet the restrictions placed on the Object will be ignored when retrieving it next time. It is important to note that updates to objects take up until the next block to be reflected usinggetObject. Changes can take up to 10 Minutes to be reflected in the final retrieval of the object.
Let's say Joe just had his 27th birthday. We want to$set his new age:
varupdate={//increase Joe's age by 1$set:{age:27}};awaitdb.commitObjectUpdate("134e366520a6f93265eb",update);
Lets say Joe just made a friend named Johan! We want to$push a friend to his best_friends array:
varupdate={//push a new friend to the best_friends array. Should be successful$push:{best_friends:{name:'Yohan B',age:30}}};awaitdb.commitObjectUpdate("134e366520a6f93265eb",update);
Lets say Joe fell into a black hole and has aged 70 years:
varupdate={$inc:{//Increase Joe's age by 70!age:70}};awaitdb.commitObjectUpdate("134e366520a6f93265eb",update);
Joe is now 97 years of age, and sadly all his friends are dead. Better get rid of Johan :(
varupdate={//pull a single friend from the best_friends array$pop:{best_friends:{}}};awaitdb.commitObjectUpdate("134e366520a6f93265eb",update);
The library allows placing restrictions on how the objects you store can be updated. The current state of an object is determined by the library using these rules when retrieving the object from Factom.
In this case,Joe Testerson is a user in a database. To facilitate that functionality, we should place some restrictions on how his object and it's fields can be updated:
letFieldRules=require('factom-objectdb/rules/FieldRules');letObjectRules=require('factom-objectdb/rules/ObjectRules');//declare object rulesletobjectRules=newObjectRules.Builder().setAddFields(false)//disable adding fields to Joe's object.setDeleteFields(false)//disable deleting fields from to Joe's object//declare field rules:.addFieldRule('_id',newFieldRules.Builder().setType('string').setEditable(false).build())//mark Joe's ID final, so it can never be changed.addFieldRule('name',newFieldRules.Builder().setType('string').setEditable(true).build())//mark Joe's name editable so he can change it later.addFieldRule('age',newFieldRules.Builder().setType('number').setEditable(true).setMin(0).setMax(100).build())//Joes age is, updatable, but will be locked to non negative number <= 100.addFieldRule('best_friends',newFieldRules.Builder().setType('array').setEditable(true).setMax(5).build())//limit Joe's best friends to to 5 in count, non deletable.build();
the field rules for the object at the same time you commit it:
//commit the initial object and rules to Factom!conststoredObject=awaitdb.commitObject(joe._id,joe,objectRules);
Please note rules are not updatable at this time. Rule declarations for objects are permanent.
To demonstrate field rules & restrictions, Lets say Joe falls into a black hole for another 1000 years, lets do the update:
constupdate={$inc:{age:1000}};awaitdb.commitObjectUpdate("134e366520a6f93265eb",update);
But now we have a problem! Increasing Joe's age by 1000 would make him over 1000 years old, which is over the maximum value we set for his age of 100. This update will be ignored the next time Joe's object is retrieved.
Object rules govern the entire object.
| Rule | Value | Description |
|---|---|---|
addfields | true|false | Can new keys be added to the object |
editfields | true|false | Can values be changed in the object |
deletefields | true|false | Can keys be removed from the object |
maxupdates | number | The maximum number of updates until this object is locked to new updates. |
fields | object | Object of FieldRules |
Object rules trump FieldRules in all cases. For example if an object is markededitfields = false, settingeditable = true for a FieldRule will not make that field editable.
| Value | Description |
|---|---|
| true|false | Can this field be edited |
| true|false | Can this field be deleted |
| true|false | Can this field be renamed |
| number | The maximum value of the field (Or length of array) |
| number | The minimum value of the field |
Let's say we want to get info on Joe's object:
constmeta=awaitdb.getObjectMetadata("134e366520a6f93265eb")
The output illustrates how the library stores and defines rules for the Object:
{"type":"meta","protocol_version":"0.0.1","timestamp":1530488933194,"object":{"_id":"5b396865cbf4239c10000001","name":"Joe Testerson","age":5,"best_friends":[]},"rules":{"editfields":true,"addfields":false,"deletefields":false,"renamefields":false,"fields":{"_id":{"editable":false,"deletable":true,"renameable":true,"type":"string"},"name":{"editable":false,"deletable":true,"renameable":true,"type":"string"},"age":{"editable":true,"deletable":false,"renameable":true,"type":"number","min":0,"max":100},"best_friends":{"editable":true,"deletable":false,"renameable":true,"type":"array","max":5}}}}
By default objects created using this library are publicly viewable and editable. This library offers several approaches to keeping objects permissioned and secure:
Objects and updates written using this library can be encrypted using AES256. Doing so results in object storage that can only be read and updated by the holder of the private encryption key.
To use AES, specify your key during initialization:
constdb=newFactomObjectDB({//... other optionsaes_key :'my awesome passphrase'//private key string or buffer});
The library uses deflate compression to shrink the data that is put into Factom. This means that the entries this library creates are not human readable. This will be made optional in the near future
Please note that once an object is initialized, AES and compression settings cannot be changed. Attempting to read an object using incorrect encryption or compression settings will result in an error.
| Query Parameter | Type | Validation | Required |
|---|---|---|---|
query | object | JSON object, valid query structure | Y |
| Query Parameter | Type | Validation | Required |
|---|---|---|---|
query | object | JSON object, valid query structure | Y |
Request body must be a valid JSON object
| Query Parameter | Type | Validation | Required |
|---|---|---|---|
rules | object | JSON object, valid object rules | N |
factom-objectdb uses chai.js
npm testApplications deserve easy, affordable, immutable data storage. Factom-objectdb wraps the required functionality into an easy to use package based on a universal structured data standard (JSON) and language (NodeJS), all for a fraction of the cost of competitors.
The price performance of immutable data solutions on Factom, like factom-objectdb, blow competitors out of the water on a $ per KB basis:
| Cost/KB | |
|---|---|
| Factom | $0.001 |
| Ethereum | $0.13 |
| NEO | $0.22 |
factom-objectdb does not require any knowledge of or integration with contract languages like Solidity. It is a language agnostic protocol can be implemented in any programming language. Anyone who can read JSON can understand objectdb.
Entering data costsEntry Credits, a fixed value, non tradable token that can be purchased by anyone, anywhere. Entry credits are not securities, cost $0.001 USD each, and enable the entry of 1 KB of data permanently into the blockchain.
- Asymmetric entry signing (Coming Soon)
- Better examples for field and object rules
- Full object and field rules table with descriptions
- Signature based validation for updates
- Make deflate compression optional for human readability
Factom-objectdb logo & Icon packs byIcons8
About
Object database implementation for the Factom protocol
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.