-
Notifications
You must be signed in to change notification settings - Fork 143
App Development API
All Ribosome types provide access to the same Holochain API, which consists in a set of functions that allow you as a Holochain app developer to commit entries to your chain, put or get data from the DHT, and expose functions to a UI or to other bridged holochain applications.
There are two kinds of values that are available to your application, system globals and app specific values.
They are displayed below using the dot notation used in JavaScript. To access these values in the Lisp ribosome replace the dots with underscores (so App.DNA.Hash
becomes App_DNA_Hash
).
-
HC.Version
Returns the version of the Holochain software -
HC.Status
Object with status value constants:Live
,Deleted
,Modified
,Rejected
,Any
for use withStatusMask
when getting entries or links. -
HC.GetMask
Object with get option value constants:Default
,Entry
,EntryType
,Sources
,All
-
HC.LinkAction
Object with link action value constants:Add
,Del
for use when committing Links entries. -
HC.PkgReq
Object with package request constants:Chain
,ChainOpt
,EntryTypes
-
HC.PkgReq.ChainOpt
Object with package requestChain
request constants:None
,Headers
,Entries
,Full
(see validation for example uses of these package request constants) -
HC.Bridge.From
Constant that will passed to bridgeGenesis in theside
parameter, and returned bygetBridges()
-
HC.Bridge.To
Constant that will passed to bridgeGenesis in theside
parameter, and returned bygetBridges()
-
App.Name
holds the Name of this Holochain from the DNA. -
App.DNA.Hash
holds the unique identifier of this Holochain's DNA. Nodes must run the same DNA to be on the same holochain. -
App.Key.Hash
holds the hash of your public key. This is your self-validating address on the DHT which functions as a kind of alias pointing to your permanent key above. -
App.Agent.Hash
holds your peer's permanent node address on the DHT. This is the hash of the second entry (identity info) on your chain. -
App.Agent.TopHash
holds the most recent agent indentity entry that has been committed to the chain. To start with its value is equivalent toApp.Agent.Hash
after a call toupdateAgent
it will have the value of the newly committed agent entry. -
App.Agent.String
holds the identity string used to initialize the holochain software withhcadmin init
If you used JSON to embed multiple properties (such as FirstName, LastName, Email, etc), they can be retrieved here as App.Agent.FirstName, etc.
These are the functions that are available for your application to call:
Returns the an application property. These properties are defined by the app developer. It returns values from the DNA file that you set as properties of your application (e.g. Name, Language, Description, Author, etc.).
The name of the property to return.
The value of the property.
var language=property("language")
Use this function to make a hash of the given entry data. This is the same hash value that would be return if entryData
were passed to commit
and by which an entry of this type would be retrievable from the DHT using get
.
a hash-string
debug(makeHash({"firstName":"Zippy","lastName":"Pinhead"}))
outputs:
QmYeinX5vhuA91D3v24YbgyLofw9QAxY6PoATrBHnRwbtt
Sends output to the debugging long.
the type of value is arbitrary and will get converted to a string according to the language conversion limitations.
N.A.
debug(makeHash({"firstName":"Zippy","lastName":"Pinhead"}))
outputs:
QmYeinX5vhuA91D3v24YbgyLofw9QAxY6PoATrBHnRwbtt
Calls an exposed function from another zome.
arguments
is a string or an object depending on the CallingType
that was specified in the function's definition in the DNA.
the value that's returned by the given function
call("clutter","post",{message:"this is a message"})
Calls an bridged function from another app. appDNAHash
is the application being called. Note that the application must have explicitly been bridged. In development use hcdev
's -bridgeTo
and -bridgeFrom
options to setup bridging. Just like in send
, the arguments
parameter is a string or an object/hash depending on the CallingType that was specified in the function's definition.
the value that's returned by the given function on the other side of the bridge.
bridge("QmY8Mzg9F69e5P9AoQPYat655HEhc1TVGs11tmfNSzkqh2","holodex","index",{message:"this is a message"})
This function allows your app to examine which bridges have been put in place.
An array of objects with aSide
property that will be either: HC.Bridge.To
or HC.Bridge.From
depending which side of the bridge the app is on.
- If
Side
is From, i.e. this is the app making calls over the bridge, then object will also contain aToApp
property with a hash of the app bridged to. - If
Side
is To, i.e. this is the app receiving calls over the bridge, then object will also contain aToken
property with the value of the token that gives access to From app.
debug(JSON.stringify(getBridges()))
outputs:
[{"Side":0,"ToApp":"QmY8Mzg9F69e5P9AoQPYat655HEhc1TVGs11tmfNSzkqto"},{"Token":"0393828348751323","Side":1}]
TODO!
sign()
verifySignature()
Attempts to commit an entry to your local, source chain. It will cause callback to your validate
function. Returns either an error or the hash of the committed entry upon success.
a hash-string of the entryData
This is an example of a function you might have in your DNA for committing a "post" entry in a blog or social-media-sharing type of app. It illustrates two aspects of committing data to you local chain. The first is committing a regular "data" style entry, and the second is committing holochain's linking type entry. When you commit a post, you would probably also want to commit links on your identity hash for people to be able to look up a list of your posts.
function post(post) {
var hash = commit("post",post); // Commits the post entry to my source chain
var me = App.Agent.Hash;
// On the DHT, puts a link on my hash to the new post
commit("post_links",{Links:[{Base:me,Link:key,Tag:"post"}]});
return hash; // Returns the hash of the new post to the caller
}
Attempts to commit an entry to your local, source chain that "replaces" a previous entry. If entryType
is not private, update
will mark replaces
as Modified on the DHT. Additionally the modification action will be recorded in the entries' header in the local chain, which will be used by validation routes.
Returns either an error or the hash of the committed entry upon success.
update("post",{message:"this is a message"},oldHash)
Commits a new agent entry to the chain, with either or both new identity information or a new public key, while revoking the old key. If revoking a key, also adds that key to the node blockedlist (which is also gossiped), as it's no longer a valid peer address.
The update options is an object that must have at least one (but can have both) of these two properties:
-
Revocation
: revocation-data-string -
Identity
: indentity-info-string
updateAgent({Identity:"newemail@example.com",Revocation:"sample revocation reason"})
Keep in mind that you will want to retrieve most data from the DHT (shared data space), so that you are seeing what the rest of the nodes on your holochain are seeing. However, there are times you will want to query private data fields, or package up up data from your source chain for sending. Use this function.
Commits a DelEntry to the local chain with given delete message, and, if the entry type of entry
is not private, moves the entry to the Deleted
status on the DHT.
remove(oldHash)
Sends a message to a node.
The return value of this function will be what ever is returned by the receive
function on the receiving node, see below.
var agentHash = send(toHash,{type:"ping"});
function receive(from,msg) {
var type = msg.type;
if (type=="ping") {
return App.Agent.Hash
}
return "unknown type"
}
This function gets called by the system when a message is received by a node. The return value of the function will be sent back to the sender and will be the result of the send
function that sent the message.
The value you return from this function will be sent back to the node that sent you the message.
See send
command above for example.
This function retrieves an entry from the local chain or the DHT.
hash:
<string>
The hash of the entry to get.
Optional Parameters*
StatusMask: int
If present, determines which status entries to return. One or more of the following modifiers (added or OR'ed):
-
HC.Status.Default
Default value. Equivalent toHC.Status.Live
-
HC.Status.Live
Get the entry if it has been successfully committed, and not deleted. If thehash
specified was modified, the chain will be followed so that the current live entry will instead be returned. -
HC.Status.Deleted
Get the entry only if it has been deleted. (TODO:Link) -
HC.Status.Modified
Return the actual entry for thishash
, even if it has since been modified. (TODO:Link) -
HC.Status.Rejected
Return an entry only if it was rejected due to validation failure (TODO:Link)
GetMask: int
If present, this option allows you to specify what information about the entry want. One or more of the following modifiers (added or OR'ed):
-
HC.GetMask.Default
Default value. Equivalent toHC.GetMask.Entry
-
HC.GetMask.Entry
Include the actual entry object in the return value as theEntry
property. -
HC.GetMask.EntryType
Include the entry type as astring
in the return value as theEntryType
property. -
HC.GetMask.Sources
Include, in the return value, an array of hashes of Node IDs of nodes who have committed thishash
. Returned as propertySources
of the return value object. -
HC.GetMask.All
Equivalent toHC.GetMask.Entry
or'ed withHC.GetMask.EntryType
or'ed withHC.GetMask.Sources
Local: boolean
If set to true, this option indicates that the get refers to the local chain only. This allows you to retrieve specific entries from your chain, which includes private entries that aren't published to the DHT.
If only GetMask
value specified or only Entry
is specified the the return value will be the actual entry value. Otherwise the return value will be an object with properties of the same name as the mask name.
Assume postHash
is the hash of a previous post. In this example we do a simple get with no options:
var r = get(postHash)
debug(r)
outputs:
"I can haz cheezburger?"`
In this example we do a get
with GetMask
options:
get(postHash,{GetMask:HC.GetMask.Entry+GetMask:HC.GetMask.EntryType+HC.GetMask.Sources})
outputs:
{"Entry":"I can haz cheezburger?","EntryType":"meow","Sources":["QmYNd9qnTaGenVF64b7bE1inFkERwzPZxDhYiDU4iM18XF"]}
getLink
TODO:links
Retrieves a list of links tagged as tag
on base
from the DHT. Options is hash map of values. Currently the options are:
-
Load: *boolean*
which if set to true tells the library to resolve get the entry values of the links. -
StatusMask: *int*
which determine which status links to return. Default is to return only Live links. You can use defined constantsHC.Status.Live/Deleted/Rejected
as the int value.
Returns an object which is has an error or a list of links.
If an error, the object will have the form: {name:"HolochainErr",message:<some error message>}
With options as {Load: false}
(which is the default) returns a list of the form {Links: [{H:"QmY..."},..]}
With options as {Load: true }
returns a list of the form {Links: [{H:"QmY...",E:"<entry value here>"},..]}
var links = getLink(base, tag,{Load:true});
There are a few functions that you must implement in your app as the Ribosome will call them as a result of other operations.
Each zome must include this function, which is called during system genesis. It executes just after the initial genesis entries are committed to your chain (1st - DNA entry, 2nd Identity entry). It enables you specify any additional operations you want performed when a node joins your holochain, for example, you may want to add some user/address/key information to the DHT to announce the presence of this new node.
All zomes which expose functions for bridging from other applications MUST also define a bridgeGenesis function (i.e. the "Bridge-To" side). Zomes which want to call functions in other applications MAY define a bridgeGenesis function and declare that they do so by setting the Zome.BridgeTo value in their DNA.
This function will be called just once with bridging is established. This allows applications to do any initialization which might be required for the bridging to operation. For example the holodex indexing mixin zome registers the node as an indexing node in the bridgeGenesis function.
side
will be an integer indicating if this is a "from" or a "to" call. The constants HC.Bridge.From and HC.Bridge.To are defined with the appropriate integer values.
dna
will be the hash of the dna on the other side of the bridge
appData
will be user specified data provided at bridge time
This function gets called when an entry is about to be committed to a source chain. Use this function to describe the agreements about data as it should be added to shared holochain. This function gets called for all entry types.
This function gets called when and entry is about to be committed to the DHT on any node. It is very likely that this validation routine should check the same data integrity as validateCommit, but, as it happens during a different part of the data life-cycle, it may require additional validation steps. [add example here] This function will only get called on entry types with "public" sharing, as they are the only types that get put to the DHT by the system.
This function gets called as a consequence of a mod
command being issued. replaces
is the hash of the entry being replaced. Often you may be validating that only agent who committed the entry can modify it. Such a validation routine might look like this:
function validateMod(entry_type, entry, header, replaces, pkg, sources) {
var valid = false;
if (entry_type=="your_type") {
var orig_sources = get(replaces, {GetMask:HC.GetMask.Sources});
//Note: error checking on this get removed for simplicity
valid = (orig_sources.length == 1 && orig_sources[0] == sources[0]);
}
return valid;
}
This function gets called as a consequence of a del
command being issued.
This function gets called when ever a links are being to the DHT. Links are added for every linking element in the special "links" entry type. Note that this is a DHT level validation routine, in that it gets called when the Link message is received by a DHT node, not when the linking entry is committed. The regular validateCommit routine gets called as usual when that linking entry is committed to the source chain.
Each one of the validate commands has a corresponding package building command that will get called on the source node as part of the validation cycle so that the appropriate data can get sent back to the node trying to validate the action. The functions are:
Note that a commit
action will trigger a call to validatePutPkg locally when committing happens as validateCommit must have the same data available to it as does validatePut.
All these functions should simply return nil if the data required by their corresponding validation function is just the minimum default of the Entry and Header of the action. Otherwise these functions must return a "Package Request" object, which specifies what data to be sent to the validating node.
A JavaScript ribosome package request function that indicates that the entire chain should be sent in the validation package, would look like this:
function validatePutPkg(entry_type) {
var req = {};
req[HC.PkgReq.Chain]=HC.PkgReq.ChainOpt.Full;
return req;
}
Or, if all that's needed is the headers of an entry types "foo" and "bar" the function would look like this:
function validatePutPkg(entry_type) {
var req = {};
req[HC.PkgReq.Chain]=HC.PkgReq.ChainOpt.Headers;
req[HC.PkgReq.EntryTypes]=["foo","bar"];
return req;
}
The validation functions are the heart of ensuring distributed data integrity. Please consider them thoroughly and carefully as your systems data integrity is built from them.
Validation functions are called under two distinct conditions.
- When data is about to be added to the local chain (validateCommit).
- Whenever any node of the DHT receives a request to store or change data in some way, the request and the changes are validated against the source chain of the person making the request (validatePut,validateLink.) These are the validation functions that check permissions and enforce any other kind of data integrity you intend to preserve. For example, in a distributed Twitter, only Bob should be able to attach (link) a "post" to Bob as if it is his, and only Bob should be able to link Bob as a "follower" of Alice. Please keep in mind that system variables like App.Agent.Hash that return your own address will not return YOUR address when being executed by a remote DHT node. Code your functions as if anyone will be running them, because they will be.
Common parameters:
-
package
the data package created by validateXPkg -
sources
an array of the sources that created were involved in taking the action
Project Links: | Holochain Overview | Code Repository | White Paper | GoDocs API Reference |
---|
Holochain is part of Ceptr, and brought to you by the MetaCurrency Project