Skip to content
This repository has been archived by the owner on Sep 15, 2020. It is now read-only.

App Development API

Eric Harris-Braun edited this page Aug 28, 2017 · 94 revisions

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.

Pre-Defined Constants

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).

System Globals and Constants

  • HC.Version Returns the version of the Holochain software
  • HC.Status Object with status value constants: Live, Deleted, Modified, Rejected, Any for use with StatusMask 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 request Chain 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 the side parameter, and returned by getBridges()
  • HC.Bridge.To Constant that will passed to bridgeGenesis in the side parameter, and returned by getBridges()

Application Globals

  • 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 to App.Agent.Hash after a call to updateAgent it will have the value of the newly committed agent entry.
  • App.Agent.String holds the identity string used to initialize the holochain software with hcadmin 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.

System Functions

property(name)

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.).

name: string

The name of the property to return.

Returns

The value of the property.

Examples

var language=property("language")

makeHash(entryData)

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.

entryData: string or object

Returns

a hash-string

Examples

debug(makeHash({"firstName":"Zippy","lastName":"Pinhead"}))

QmYeinX5vhuA91D3v24YbgyLofw9QAxY6PoATrBHnRwbtt

debug(value)

Sends output to the debugging long.

value: any-type

the type of value is arbitrary and will get converted to a string according to the language conversion limitations.

Returns

N.A.

Examples

debug(makeHash({"firstName":"Zippy","lastName":"Pinhead"}))

QmYeinX5vhuA91D3v24YbgyLofw9QAxY6PoATrBHnRwbtt

call(zomeName, functionName, arguments)

Calls an exposed function from another zome.

zomeName: string

functionName: string

arguments: string or object

arguments is a string or an object depending on the CallingType that was specified in the function's definition in the DNA.

Returns

the value that's returned by the given function

Examples

call("clutter","post",{message:"this is a message"})

bridge(appDNAHash, zomeName, functionName, arguments)

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.

appDNAHash: hash-string

zomeName: string

functionName: string

arguments: string or object

Returns

the value that's returned by the given function on the other side of the bridge.

Examples

bridge("QmY8Mzg9F69e5P9AoQPYat655HEhc1TVGs11tmfNSzkqh2","holodex","index",{message:"this is a message"})

getBridges()

This function allows your app to examine which bridges have been put in place.

Returns

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 from app, then object will also contain a ToApp property with a hash of the app bridged to.
  • If Side is To, i.e. this is the from app, then object will also contain a Token property with the value of the token that gives access to From app.

Examples

debug(JSON.stringify(getBridges()))

outputs:

[{"Side":0,"ToApp":"QmY8Mzg9F69e5P9AoQPYat655HEhc1TVGs11tmfNSzkqto"},{"Token":"0393828348751323","Side":1}]

Functions for Chain Actions (may have DHT side-effects)

commit(entryType,entryData)

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.

entryType: string

entryData: string or object

Returns

a hash-string of the entryData

Examples

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
}

update(entryType,entryData,replaces)

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.

entryType: string

entryData: string or object

replaces: hash-string

Returns

Returns either an error or the hash of the committed entry upon success.

Examples

update("post",{message:"this is a message"},oldHash)

updateAgent(updateOptions)

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.

updateOptions: object

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

Returns

Examples

updateAgent({Identity:"newemail@example.com",Revocation:"sample revocation reason"})

query (still being implemented for direct query your local chain)

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.

remove(entry, message)

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.

entry: hash-string

message: string

Returns

Examples

remove(oldHash)

Node-to-Node communication Functions

send(to, message)

Sends a message to a node.

to: hash-string

message: string

Returns

The return value of this function will be what ever is returned by the receive function on the receiving node, see below.

Examples

var agentHash = send(toHash,{type:"ping"});

function receive(from,msg) {
    var type = msg.type;
    if (type=="ping") {
        return App.Agent.Hash
    }
    return "unknown type"
}

receive(from, message)

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.

from: hash-string

message: string

Returns

The value you return from this function will be sent back to the node that sent you the message.

Examples

See send command above for example.

Functions for DHT query

get

This function retrieves an entry from the local chain or the DHT.

Required Parameters

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 to HC.Status.Live
  • HC.Status.Live Get the entry if it has been successfully committed, and not deleted. If the hash 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 this hash, 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 to HC.GetMask.Entry
  • HC.GetMask.Entry Include the actual entry object in the return value as the Entry property.
  • HC.GetMask.EntryType Include the entry type as a string in the return value as the EntryType property.
  • HC.GetMask.Sources Include, in the return value, an array of hashes of Node IDs of nodes who have committed this hash. Returned as property Sources of the return value object.
  • HC.GetMask.All Equivalent to HC.GetMask.Entry or'ed with HC.GetMask.EntryType or'ed with HC.GetMask.Sources

Returns

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.

Examples

assume postHash is the hash of a previous post.

var r = get(postHash)
debug(r)

outputs: "I can haz cheezburger?"

get(postHash,{GetMask:HC.GetMask.Entry+GetMask:HC.GetMask.EntryType+HC.GetMask.Sources})

returns: {"Entry":"I can haz cheezburger?","EntryType":"meow","Sources":["QmYNd9qnTaGenVF64b7bE1inFkERwzPZxDhYiDU4iM18XF"]}

Related Items

getLink

TODO:links

getLink(base, tag [, options])

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 constants HC.Status.Live/Deleted/Rejected as the int value.

base: hash-string

tag: string

Returns

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>"},..]}

Examples

var links = getLink(base, tag,{Load:true});

Required Application Functions

There are a few functions that you must implement in your app as the Ribosome will call them as a result of other operations.

genesis()

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.

bridgeGenesis(side, dna, appData)

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: int

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: hash-string

dna will be the hash of the dna on the other side of the bridge

apData: string

appData will be user specified data provided at bridge time

Validation functions:

validateCommit(entryType, entry, header, package, sources)

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.

validatePut(entryType, entry, header, package, sources)

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.

validateMod(entryType, entry, header, replaces, package, sources)

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;
}

validateDel(entryType, hash, package, sources)

This function gets called as a consequence of a del command being issued.

validateLink(linkEntryType, baseHash, links, pkg, sources)

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.

Validation Packaging

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:

validatePutPkg(entryType)

validateModPkg(entryType)

validateDelPkg(entryType)

validateLinkPkg(entryType)

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.

Examples

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.

  1. When data is about to be added to the local chain (validateCommit).
  2. 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

Please see our new documentation site at developer.holochain.org.

Intro

External Links

Holochain Core Development

Dev pages, need integrating into the wiki

Docker install for Devs

Clone this wiki locally