iris-lib

0.0.151

Channel

Private communication channel between two or more participants (Gun public keys). Can be used independently of other Iris stuff.

Used as a core element of iris-messenger.


Key-value API

channel.put(key, value) and channel.on(key, callback).

Note that each participant has their own versions of each key-value — they don't overwrite each other. channel.on() callback returns them all by default and has a parameter that indicates whose value you got.

While values are encrypted, encryption of keys is not implemented yet.

Message API

channel.send() and channel.getMessages() for timestamp-indexed chat-style messaging.

Message data is encrypted, but timestamps are public so that peers can return your messages in a sequential order.


You can open a channel with yourself for a private key-value space or a "note to self" type chat with yourself.

Note! As of April 2020 Gun.SEA hashing function is broken on Safari. Channels don't work on Safari unless you patch sea.js by adding this line.

Privacy disclaimer: Channel ids, data values and messages are encrypted, but message timestamps are unencrypted so that peers can return them to you in a sequential order. By looking at the unencrypted timestamps (or Gun subscriptions), it is possible to guess who are communicating with each other. This could be improved by indexing messages by day only, so making the guess would be more difficult, while you could still return them in a semi-sequential order.

new Channel(options: Object)
Parameters
options (Object)
Name Description
options.key string your keypair
options.gun Object gun instance
options.participants any (optional) string or string array or permissions object ({'pub1':{read:true,write:true,admin:false},'pub2'...}) of participant public keys (your own key is included by default)
options.chatLink string (optional) chat link instead of participants list
options.uuid string (group channels only) unique channel identifier. Leave out for new channel.
options.name string (group channels only) channel name
Example
// Copy & paste this to console at https://iris.to or other page that has gun, sea and iris-lib
// Due to an unsolved bug, someoneElse's messages only start showing up after a reload

var gun1 = new Gun('https://gun-us.herokuapp.com/gun');
var gun2 = new Gun('https://gun-us.herokuapp.com/gun');
var myKey = await iris.Key.getDefault();
var someoneElse = localStorage.getItem('someoneElsesKey');
if (someoneElse) {
 someoneElse = JSON.parse(someoneElse);
} else {
 someoneElse = await iris.Key.generate();
 localStorage.setItem('someoneElsesKey', JSON.stringify(someoneElse));
}

iris.Channel.initUser(gun1, myKey); // saves myKey.epub to gun.user().get('epub')
iris.Channel.initUser(gun2, someoneElse);

var ourChannel = new iris.Channel({key: myKey, gun: gun1, participants: someoneElse.pub});
var theirChannel = new iris.Channel({key: someoneElse, gun: gun2, participants: myKey.pub});

var myChannels = {}; // you can list them in a user interface
function printMessage(msg, info) {
 console.log(`[${new Date(msg.time).toLocaleString()}] ${info.from.slice(0,8)}: ${msg.text}`)
}
iris.Channel.getChannels(gun1, myKey, channel => {
 var pub = channel.getCurrentParticipants()[0];
 gun1.user(pub).get('profile').get('name').on(name => channel.name = name);
 myChannels[pub] = channel;
 channel.getMessages(printMessage);
 channel.on('mood', (mood, from) => console.log(from.slice(0,8) + ' is feeling ' + mood));
});

// you can play with these in the console:
ourChannel.send('message from myKey');
theirChannel.send('message from someoneElse');

ourChannel.put('mood', 'blessed');
theirChannel.put('mood', 'happy');
https://github.com/irislib/iris-lib/blob/master/__tests__/Channel.js
Static Members
getOurSecretChannelId(gun, pub, pair)
getTheirSecretChannelId(gun, pub, pair)
getChannels(gun, keypair, callback, listenToChatLinks)
addChatButton(options)
setActivity(gun, activity)
getActivity(gun, pubKey, callback)
initUser(gun, key)
deleteChannel(gun, key, pub)
Instance Members
mute(participant)
block(participant)
getCurrentParticipants()
getParticipants(callback)
getId()
getMessages(callback)
getLatestMsg(callback)
setMyMsgsLastSeenTime(time)
getMyMsgsLastSeenTime(callback)
getTheirMsgsLastSeenTime(callback)
addParticipant(pub, save, permissions)
send(msg)
save()
put(key, value)
on(key, callback, from)
setTyping(isTyping, timeout)
getTyping(callback, timeout)
getChatBox()

SocialNetwork

Experimental. Unlike Channel, this is probably not the most useful class yet.

The essence of Iris: A database of Contacts and SignedMessages within your web of trust.

NOTE: these docs reflect the latest commit at https://github.com/irislib/iris-lib

To use someone else's index (read-only): set options.pubKey

To use your own index: set options.keypair or omit it to use Key.getDefaultKey().

Each added SignedMessage updates the SignedMessage and Contacts indexes and web of trust accordingly.

You can pass options.gun to use custom gun storages and networking settings.

Wait for index.ready promise to resolve before calling instance methods.

new SocialNetwork(options: Object): SocialNetwork
Parameters
options (Object) see default options in example
Returns
SocialNetwork: index object
Example
https://github.com/irislib/iris-lib/blob/master/__tests__/SocialNetwork.js

Default options:
{
 keypair: undefined,
 pubKey: undefined,
 gun: undefined,
 self: undefined,
 indexSync: {
   importOnAdd: {
     enabled: true,
     maxMsgCount: 500,
     maxMsgDistance: 2
   },
   subscribe: {
     enabled: true,
     maxMsgDistance: 1
   },
   query: {
     enabled: true
   },
   msgTypes: {
     all: false,
     rating: true,
     verification: true,
     unverification: true
   },
   debug: false
 }
}
Instance Members
addContact(attributes, follow)
getContacts(opt)
getRootContact()
getChannels(callback)
addMessage(msg, options)
getMessages(opt)

Contact

An Iris Contact, such as person, organization or group. More abstractly speaking: an Identity.

Usually you don't create Contacts yourself, but get them from SocialNetwork methods such as get() and search().

new Contact(gun: Object, linkTo: any)
Parameters
gun (Object) node where the Contact data lives
linkTo (any)
Static Members
appendSearchWidget(parentElement, index)
appendSearchWidget(parentElement, index)
Instance Members
sent(index, options)
sent(index, options)
received(index, options)
received(index, options)
verified(attribute)
verified(attribute)
profileCard()
profileCard()
identicon(options)
identicon(options)

Contact

An Iris Contact, such as person, organization or group. More abstractly speaking: an Identity.

Usually you don't create Contacts yourself, but get them from SocialNetwork methods such as get() and search().

new Contact(gun: Object, linkTo: any)
Parameters
gun (Object) node where the Contact data lives
linkTo (any)
Static Members
appendSearchWidget(parentElement, index)
appendSearchWidget(parentElement, index)
Instance Members
sent(index, options)
sent(index, options)
received(index, options)
received(index, options)
verified(attribute)
verified(attribute)
profileCard()
profileCard()
identicon(options)
identicon(options)

SignedMessage

Signed message object. Your friends can index and relay your messages, while others can still verify that they were signed by you.

Fields: signedData, signer (public key) and signature.

signedData has an author, signer, type, time and optionally other fields.

signature covers the utf8 string representation of signedData. Since messages are digitally signed, users only need to care about the message signer and not who relayed it or whose index it was found from.

signer is the entity that verified its origin. In other words: message author and signer can be different entities, and only the signer needs to use Iris.

For example, a crawler can import and sign other people's messages from Twitter. Only the users who trust the crawler will see the messages.

"Rating" type messages, when added to an SocialNetwork, can add or remove Identities from the web of trust. Verification/unverification messages can add or remove Attributes from an Contact. Other types of messages such as social media "post" are just indexed by their author, recipient and time.

Constructor: creates a message from the param obj.signedData that must contain at least the mandatory fields: author, recipient, type and time. You can use createRating() and createVerification() to automatically populate some of these fields and optionally sign the message.

new SignedMessage(obj: Object)
Parameters
obj (Object)
Example
https://github.com/irislib/iris-lib/blob/master/__tests__/SignedMessage.js

Rating message:
{
  signedData: {
    author: {name:'Alice', key:'ABCD1234'},
    recipient: {name:'Bob', email:'bob@example.com'},
    type: 'rating',
    rating: 1,
    maxRating: 10,
    minRating: -10,
    text: 'Traded 1 BTC'
  },
  signer: 'ABCD1234',
  signature: '1234ABCD'
}

Verification message:
{
  signedData: {
    author: {name:'Alice', key:'ABCD1234'},
    recipient: {
      name: 'Bob',
      email: ['bob@example.com', 'bob.saget@example.com'],
      bitcoin: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'
    },
    type: 'verification'
  },
  signer: 'ABCD1234',
  signature: '1234ABCD'
}
Static Members
create(signedData, signingKey)
createVerification(signedData, signingKey)
createRating(signedData, signingKey)
deserialize(s)
setReaction(gun, msg, reaction)
Instance Members
getAuthorIterable()
getRecipientIterable()
getAuthorArray()
getRecipientArray()
getSignerKeyID()
isPositive()
isNegative()
isNeutral()
sign(key)
getAuthor(index)
getRecipient(index)
getHash()
verify()
serialize()

Key

Key management utils. Wraps GUN's Gun.SEA. https://gun.eco/docs/Gun.SEA

new Key()
Static Members
getActiveKey(datadir, keyfile)
getActiveKey(datadir, keyfile)
setActiveKey(key, save, datadir, keyfile)
setActiveKey(key, save, datadir, keyfile)
toString(key)
toString(key)
getId(key)
getId(key)
fromString(str)
fromString(str)
generate()
generate()
sign(msg, pair)
sign(msg, pair)
verify(msg, pubKey)
verify(msg, pubKey)

Key

Key management utils. Wraps GUN's Gun.SEA. https://gun.eco/docs/Gun.SEA

new Key()
Static Members
getActiveKey(datadir, keyfile)
getActiveKey(datadir, keyfile)
setActiveKey(key, save, datadir, keyfile)
setActiveKey(key, save, datadir, keyfile)
toString(key)
toString(key)
getId(key)
getId(key)
fromString(str)
fromString(str)
generate()
generate()
sign(msg, pair)
sign(msg, pair)
verify(msg, pubKey)
verify(msg, pubKey)

Attribute

A simple key-value pair with helper functions.

Constructor: new Attribute(value), new Attribute(type, value) or new Attribute({type, value})

new Attribute(a: string, b: string)
Parameters
a (string)
b (string)
Static Members
getUuid()
getUuid()
getUniqueIdValidators()
getUniqueIdValidators()
isUniqueType(type)
isUniqueType(type)
guessTypeOf(value)
guessTypeOf(value)
equals(a, b)
equals(a, b)
Instance Members
isUniqueType()
isUniqueType()
equals(a)
equals(a)
uri()
uri()
identicon(options)
identicon(options)

Attribute

A simple key-value pair with helper functions.

Constructor: new Attribute(value), new Attribute(type, value) or new Attribute({type, value})

new Attribute(a: string, b: string)
Parameters
a (string)
b (string)
Static Members
getUuid()
getUuid()
getUniqueIdValidators()
getUniqueIdValidators()
isUniqueType(type)
isUniqueType(type)
guessTypeOf(value)
guessTypeOf(value)
equals(a, b)
equals(a, b)
Instance Members
isUniqueType()
isUniqueType()
equals(a)
equals(a)
uri()
uri()
identicon(options)
identicon(options)

Collection

Gun object collection that provides tools for indexing and search. Decentralize everything!

If opt.class is passed, object.serialize() and opt.class.deserialize() must be defined.

Supports search from multiple indexes. For example, retrieve message feed from your own index and your friends' indexes.

TODO: aggregation TODO: example TODO: scrollable and stretchable "search result window"

new Collection(opt: Object)
Parameters
opt (Object = {}) {gun, class, indexes = [], askPeers = true, name = class.name}
Instance Members
put(object, opt)
get(opt)