Option 2: Decentralized communication platform
The Orbis SDK allows you to create decentralized messaging system. All messages are decentralized and stored on Ceramic but encrypted using Lit Protocol.
Because all of the messages sent using the Orbis protocol are using the same schemas, messages sent using your application can be accessed from many different apps and vice-versa.
Step 1: Creating a conversation
A message needs to be part of a conversation
so we need to create a conversation
object before being able to send messages. Let’s see how it works:
import React, { useState, useEffect } from 'react';
/** Import Orbis SDK */
import { Orbis } from "@orbisclub/orbis-sdk";
/**
* Initialize the Orbis class object:
* You can make this object available on other components by passing it as a prop or by using a context.
*/
let orbis = new Orbis();
export default function App() {
/** The user object returned by the connect function can be stored in state */
const [user, setUser] = useState();
/** Calls the Orbis SDK and handle the results */
async function connect() {
let res = await orbis.connect();
/** Check if connection is successful or not */
if(res.status == 200) {
console.log("Connected to Ceramic with: ", res.did);
setUser(res.did);
} else {
console.log("Error connecting to Ceramic: ", res);
alert("Error connecting to Ceramic.");
}
}
return(
<div>
{user ?
<>
<p>Connected with: {user}</p>
<CreateConversation orbis={orbis} />
</>
:
<button onClick={() => connect()}>Connect</button>
}
</div>
);
}
function CreateConversation({orbis}) {
const [loading, setLoading] = useState(false);
const [text, setText] = useState("");
/** We are calling the Orbis SDK to share a new post from this user */
async function createConversation() {
setLoading(true);
/**
* The createConversation() function accept a JSON object that must contain a 'recipients' object
* which is an array containing all of the 'dids' that will be part of the conversation. The sender's
* 'did' will be added automatically.
*/
let res = await orbis.createConversation({recipients: [text]});
/** Check if conversation was created with success or not */
if(res.status == 200) {
console.log("Save this conversation_id to use in the following examples: ", res.doc);
alert("Save this conversation_id to use in the following examples: " + res.doc);
} else {
console.log("Error creating conversation: ", res);
alert("Error creating conversation.");
}
setLoading(false);
}
return(
<div>
{/** You can use this did to test: did:pkh:eip155:1:0x222bc13f54b2f14e41945c9f2f3b9f00b4ec9b40 */}
<input placeholder="Recipient's DiD" type="text" value={text} onChange={(e) => setText(e.target.value)} />
{loading ?
<button>Loading...</button>
:
<button onClick={() => createConversation()}>Create conversation</button>
}
</div>
);
}
Step 2: Sending a message to a conversation
On Orbis, each message is encrypted using LitProtocol, so the DMs sent using Orbis are still stored on Ceramic but in an encrypted way, here is an example:
Now that we created a conversation, we can use the conversation_id
created in the previous example to send messages to this conversation.
import React, { useState, useEffect } from 'react';
/** Import Orbis SDK */
import { Orbis } from "@orbisclub/orbis-sdk";
/**
* Initialize the Orbis class object:
* You can make this object available on other components by passing it as a prop or by using a context.
*/
let orbis = new Orbis();
/** Use the conversation_id previously created here */
let conversation_id;
if(!conversation_id) {
alert("You need to use the conversation_id previously created in this example.")
}
export default function App() {
/** The user object returned by the connect function can be stored in state */
const [user, setUser] = useState();
/** Calls the Orbis SDK and handle the results */
async function connect() {
let res = await orbis.connect();
/** Check if connection is successful or not */
if(res.status == 200) {
console.log("Connected to Ceramic with: ", res.did);
setUser(res.did);
} else {
console.log("Error connecting to Ceramic: ", res);
alert("Error connecting to Ceramic.");
}
}
return(
<div>
{user ?
<>
<p>Connected with: <b>{user}</b></p>
{conversation_id ?
<>
<p>Sending a message to conversation: <b>{conversation_id}</b></p>
{/** Paste the conversation_id created in previous example here: */}
<SendMessage conversation_id={conversation_id} orbis={orbis} />
</>
:
<p>You need to use the <b>conversation_id</b> created in the previous example.</p>
}
</>
:
<button onClick={() => connect()}>Connect</button>
}
</div>
);
}
/** Used to write and send direct messages to a conversation using the Orbis SDK */
function SendMessage({orbis, conversation_id}) {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState();
/** We are calling the Orbis SDK to share a new post from this user */
async function send() {
setLoading(true);
/**
* The sendMessage() function accept a JSON object that must contain the 'conversation_id'
* and 'body' key.
*/
let res = await orbis.sendMessage({conversation_id: conversation_id, body: message});
/** Check if conversation was created with success or not */
if(res.status == 200) {
alert("Message sent!");
console.log("Message sent with stream_id: ", res.doc);
setLoading(false);
setMessage("");
} else {
console.log("Error sending message: ", res);
alert("Error sending sending. You might need to refresh the page.");
}
}
return(
<div>
<textarea placeholder="Your message..." value={message} onChange={(e) => setMessage(e.target.value)} />
{loading ?
<button>Loading...</button>
:
<button onClick={() => send()}>Send</button>
}
</div>
);
}
Step 3: Retrieving messages from a conversation
We will keep on using the conversation_id created in the first step in the example. We are now going to load the previous message sent in this conversation and decrypt them using the Orbis SDK.
import React, { useState, useEffect } from 'react';
/** Import Orbis SDK */
import { Orbis } from "@orbisclub/orbis-sdk";
/**
* Initialize the Orbis class object:
* You can make this object available on other components by passing it as a prop or by using a context.
*/
let orbis = new Orbis();
/** Use the 'conversation_id' created in the previous example here */
let conversation_id = null;
if(!conversation_id) {
alert("You need to use the conversation_id previously created in this example.")
}
export default function App() {
/** The user object returned by the connect function can be stored in state */
const [user, setUser] = useState();
/** Calls the Orbis SDK and handle the results */
async function connect() {
let res = await orbis.connect();
/** Check if connection is successful or not */
if(res.status == 200) {
console.log("Connected to Ceramic with: ", res.did);
setUser(res.did);
} else {
console.log("Error connecting to Ceramic: ", res);
alert("Error connecting to Ceramic.");
}
}
return(
<div>
{user ?
<>
<p>Connected with: {user}</p>
{/** Paste the conversation_id created in previous example here: */}
<SendMessage conversation_id={conversation_id} orbis={orbis} />
<Messages conversation_id={conversation_id} orbis={orbis} />
</>
:
<button onClick={() => connect()}>Connect</button>
}
</div>
);
}
/** We will use this component to load, decrypt and display all the messages sent in this conversation */
function Messages({orbis, conversation_id}) {
const [loading, setLoading] = useState(true);
const [messages, setMessages] = useState([]);
/** We trigger the query when the component is mounted */
useEffect(() => {
if(conversation_id) {
loadMessages()
}
}, []);
/** Query our API to load the messages */
async function loadMessages() {
setLoading(true);
let { data, error, status } = await orbis.getMessages(conversation_id);
if(data) {
setMessages(data);
setLoading(false);
}
}
/** Show loading state or messages sent. */
if(loading) {
return <p>Loading...</p>
}
if(messages && messages.length > 0) {
return messages.map((message, key) => {
return(
<OneMessage message={message} orbis={orbis} key={key} />
)
});
} else {
return <p>No messages shared in this conversation.</p>
}
}
/** This component is being used to decrypt and display one message */
function OneMessage({message, orbis}) {
const [body, setBody] = useState();
/** We call the decrypt function when the component mounts */
useEffect(() => {
if(message) {
decrypt();
}
}, [message])
/**
* Because the messages sent using Orbis are encrypted we need to decrypt it
* before displaying the content on the screen.
*/
async function decrypt() {
let res = await orbis.decryptMessage(message.content);
setBody(res.result);
}
return(
<div>
<p><b>From: {message.creator}</b></p>
<p>{body ? body : "-"}</p>
</div>
)
}
/** Used to write and send direct messages to a conversation using the Orbis SDK */
function SendMessage({orbis, conversation_id}) {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState();
/** We are calling the Orbis SDK to share a new post from this user */
async function send() {
setLoading(true);
/**
* The sendMessage() function accept a JSON object that must contain the 'conversation_id'
* and 'body' key.
*/
let res = await orbis.sendMessage({conversation_id: conversation_id, body: message});
/** Check if conversation was created with success or not */
if(res.status == 200) {
alert("Message sent!");
console.log("Message sent with stream_id: ", res.doc);
setLoading(false);
setMessage("");
} else {
console.log("Error sending message: ", res);
alert("Error sending sending. You might need to refresh the page.");
}
}
return(
<div>
<textarea placeholder="Your message..." value={message} onChange={(e) => setMessage(e.target.value)} />
{loading ?
<button>Loading...</button>
:
<button onClick={() => send()}>Send</button>
}
</div>
);
}
Last updated