This is a complete implementation of the Edsu client protocol. It's very low level and non-opinionated - it's meant to be wrapped by further libraries before being used in apps. Though if your needs are simple it can do fine in a pinch.

Including this script introduces several classes to the namespace:

EdsuErrA collection of Symbols that are used to indicate errors
EdsuInfoA collection of Symbols that are used to indicate non-errors
EdsuCacheManages the Edsu block cache
EdsuUseful constants and functions
EdsuConnRawA class used to create an Edsu connection

EdsuErr and EdsuInfo

These are used to interpret the results of calls to code in this library. If any call is capable of failing, it will return an object, always following one of the following two forms:

    ok: true,

    err: EdsuErr.notFound,
    debug: 'block not found'
In each of these cases there may be more items, depending on the context. In the case of an error, err will always be a Symbol from the EdsuErr object. The symbols in EdsuInfo are used in a less rigorous way - wherever they are needed.


This is a static class, an in-memory cache of all blocks that are loaded from the network. The only function which makes sense for devs to use directly is setOpts(), which takes an object with one property: memSizeKb. This is the targetted amount of memory it will use (across all Edsu connections in the tab) - ejecting lesser-used and older blocks if the target is exceeded.


Edsu is a static class containing the following functions (complete descriptions coming soon):

encodeBinaryBlock(contents, hashes, opts)
encodeTextBlock(text, opts)
encodeEsonToBlockBytes(eson, opts)
hmacSha256(key, text)


This class is meant to be instantiated with new, at which point it will represent an Edsu connection.

Even though it is low level, it handles the parts of using an Edsu connection which have an obvious implementation: automatic reconnections, retrying of idempotent operations (which is nearly all of them), and managing subscription state.


An instantiation could look like this:

let conn = new EdsuConnRaw('ada@edsu.org', {
        token: '0_WurX5RmWbDQ6v2ZorMgJ19Gpdq',
        visitorUsername: 'bem@edsu.org',
        idleTriggerS: 2,
    }, {
        err: e => console.log('Error: ', e),
        info: e => console.log('Info: ', e),

The above would connect to ada@edsu.org's Edsu account, claming to be Bem, and providing a visitor token as proof. The connection is set to idle (i.e. silently disconnect and wait for more activity before reconnecting) after two seconds of inactivity (note that a non-zero number of subscriptions will stop idling until they are stopped). If omitted the default idle trigger is 256 seconds. If the connection drops and it was not being used (i.e. there are no ongoing operations or subscriptions), the connection will be idled instead of trying to re-connect immediately.

To make the connection an owner connection, simply omit the visitorUsername property and substitute one of Ada's owner tokens for the token property.

The err property is a callback on any connection-killing error. Calls here will have an err property, as well as reconnecting, which indicates whether the code is trying to reconnect - if this is false, the connection is closed and will stay that way.

The err property is a callback for when certain events happen. Calls here will have an ok: true, as well as info, which will be one of EdsuInfo.closed, EdsuInfo.authenticated, EdsuInfo.idling, or EdsuInfo.reconnecting.

In first case, it means that the connection has closed, either because of a normal request or an error - in the latter case the err callback will have already been called.

In the second case, it means that the requested authentication (owner or visitor) has been completed successfully.

In the the third and fourth cases, it means that the connection has been dropped: either because of an error, or it is being idled, respectively.

From the moment the EdsuConnRaw object is instantiated you can ask it to perform whichever Edsu operations you please - they will be internally queued and executed when possible (i.e. when the connection is (re)established, or when authentication succeeds, depending on the op). The actual connection state is abstracted and is generally not something you as a dev need to worry about, unless it fails into a non-recoverable state.

The operations are made available via the following methods (complete descriptions coming soon):

setOpts(opts) // opts: idleTriggerS
setCbs(cbs) // cbs: err, info
blockPut(bytes, opts, cbs) // opts: timeoutMs, noRetry | cbs: ok, err
blockGet(hash, opts, cbs) // opts: chain, timeoutMs, noRetry | cbs: ok, err
namePut(name, hash, opts, cbs) // opts: existingHash, timeoutMs, noRetry | cbs: ok, err
nameDel(name, existingHash, opts, cbs) // opts: timeoutMs, noRetry | cbs: ok, err
nameGet(name, opts, cbs) // opts: chain, timeoutMs, noRetry | cbs: ok, err
nameAppend(name, hash, opts, cbs) // opts: timeoutMs, retry | cbs: ok, err
ping(opts, cbs) // opts: timeoutMs, noRetry | cbs: ok, err
subPut(name, opts, cbs) // opts: existingHash, once, durationS, chain | cbs: notify, err