Introduction
In this guide, we'll build a small distributed App (DApp) from the ground up using the Java client library. The techniques you’ll learn in this tutorial are fundamental to make any DApp on Radix, and mastering it will give you a better understanding of the Radix distributed ledger.
About our example DApp
As our example DApp for this guide, we'll be building a simple ChatBot that receives and replies messages sent to a specific Radix address. With our small ChatBot DApp you'll learn to:
-Bootstrap and connect to the Radix Distributed Ledger
-Create a Radix Identity
-Create a Radix Address from this identity
-Send and receive encrypted messages to other Radix addresses
Don't worry if you're new to Radix's concepts, as we will review the basic building blocks along the way.
Basic setup
Our first step is to set you up so you can start building your first Java DApp with Radix.
Installation
You can install the radixdlt-java
library via gradle:
repositories {
maven { url 'https://jitpack.io' }
}
implementation 'com.radixdlt:radixdlt-java:0.9.3'
Recommendations
For this guide, we will assume that you have some familiarity with Java, but you should be able to follow along even if you’re coming from a different programming language.
If you need to review Java, we recommend reading this guide.
We’ll also assume that you’re familiar with programming concepts like functions, objects, arrays, and classes. Additionally, knowledge of reactive and observable patterns is helpful but not required.
Overview
Now that you’re set up, feel free to review our glossary so we can share a common language:
-Universe
-Shards
-Nodes
-Atoms
-Account
-Address
-Identity
Building a ChatBot
Now that we have done a brief overview of the concepts behind Radix and we share a common language, we are ready to begin building our example ChatBot DApp using the radixdlt-java
library.
Connecting to the network
The first step, before we can interact with the ledger, is to choose which Universe we want to connect to. In this case, we will use the ALPHANET universe configuration since it's our main testing environment.
We start by creating a ChatBot class and initializing the connection to a Radix Universe using the RadixUniverse.bootstrap()
method:
import com.radixdlt.client.core.RadixUniverse;
public class ChatBot {
static {
RadixUniverse.bootstrap(Bootstrap.ALPHANET);
}
public ChatBot() {
}
}
Creating a Radix Identity
Next, we need to generate a RadixIdentity
which will handle the private/public key logic on behalf of the ChatBot. We do it by calling the SimpleRadixIdentity()
constructor:
public class ChatBot {
static {
RadixUniverse.bootstrap(Bootstrap.ALPHANET);
}
public ChatBot() throws IOException {
// Load Identity
final RadixIdentity chatBotIdentity = new SimpleRadixIdentity("chatbot.key");
}
}
Note:
thechatbot.key
file is where the private key will be saved and loaded.
Creating a Radix Address
Now, using the public key of the identity, we can generate a unique Radix address, which is the ChatBot's unique identifier in the Radix Universe.
public class ChatBot {
static {
RadixUniverse.bootstrap(Bootstrap.ALPHANET);
}
private final RadixAddress address;
public ChatBot() throws IOException {
// Load Identity
final RadixIdentity chatBotIdentity = new SimpleRadixIdentity("chatbot.key");
final ECPublicKey publicKey = chatBotIdentity.getPublicKey();
this.address = RadixUniverse.getInstance().getAddressFrom(publicKey);
}
}
Receiving messages
Once we have created an address for the ChatBot, we can begin to receive messages. To get a message we need to:
-Initialize Radix Messaging module
-Subscribe a listener to our address
-Decrypt each message (using our identity)
-Print every message we receive
public class ChatBot {
static {
RadixUniverse.bootstrap(Bootstrap.ALPHANET);
}
private final RadixAddress address;
public ChatBot() throws IOException {
// Load Identity
final RadixIdentity chatBotIdentity = new SimpleRadixIdentity("chatbot.key");
final ECPublicKey publicKey = chatBotIdentity.getPublicKey();
this.address = RadixUniverse.getInstance().getAddressFrom(publicKey);
// Subscribe/Decrypt messages
final Observable<RadixMessage> messageObservables = RadixMessaging.getInstance()
.getAllMessagesDecrypted(chatBotIdentity);
// Print messages
messageObservables.subscribe(System.out::println);
}
}
Sending messages
Now that the ChatBot can receive messages, we can make the bot reply by sending a message back to the sender. We do this by:
Subscribing another listener to our address
Filtering messages (so we don't respond to our own messages)
Creating and sending an encrypted echo message to the original sender
public class ChatBot {
static {
RadixUniverse.bootstrap(Bootstrap.ALPHANET);
}
private final RadixAddress address;
public ChatBot(Function<String,String> chatBotAlgorithm) {
// Load Identity
final RadixIdentity chatBotIdentity = new SimpleRadixIdentity("chatbot.key");
final ECPublicKey publicKey = chatBotIdentity.getPublicKey();
this.address = RadixUniverse.getInstance().getAddressFrom(publicKey);
// Subscribe/Decrypt messages
final Observable<RadixMessage> messageObservables = RadixMessaging.getInstance()
.getAllMessagesDecrypted(chatBotIdentity);
// Print messages
messageObservables.subscribe(System.out::println);
// Chatbot replies
messageObservables
.filter(message -> !message.getFrom().equals(address)) // Don't reply to ourselves!
.filter(message -> Math.abs(message.getTimestamp() - System.currentTimeMillis()) < 60000) // Only reply to recent messages
.subscribe(message ->
RadixMessaging.getInstance()
.sendMessage(chatBotAlgorithm.apply(message.getContent()), chatBotIdentity, message.getFrom());
}
}
Finishing touches
At this point, we have all the basic building blocks for our simple ChatBot DApp. Now, to have a complete and functional DApp, let's add some finishing touches:
-Use a Function<String,String>
to represent the ChatBot algorithm to make it easily extensible
-Build a main
method to run and test by sending a message to its address
import com.radixdlt.client.core.Bootstrap;
import com.radixdlt.client.core.RadixUniverse;
import com.radixdlt.client.core.address.RadixAddress;
import com.radixdlt.client.core.crypto.ECPublicKey;
import com.radixdlt.client.core.identity.OneTimeUseIdentity;
import com.radixdlt.client.core.identity.RadixIdentity;
import com.radixdlt.client.core.identity.SimpleRadixIdentity;
import com.radixdlt.client.core.network.AtomSubmissionUpdate;
import com.radixdlt.client.messaging.RadixMessage;
import com.radixdlt.client.messaging.RadixMessaging;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import java.util.function.Function;
public class ChatBot {
static {
RadixUniverse.bootstrap(Bootstrap.ALPHANET);
}
private final RadixAddress address;
public ChatBot(Function<String,String> chatBotAlgorithm) throws Exception {
// Load Identity
final RadixIdentity chatBotIdentity = new SimpleRadixIdentity("chatbot.key");
final ECPublicKey publicKey = chatBotIdentity.getPublicKey();
this.address = RadixUniverse.getInstance().getAddressFrom(publicKey);
// Subscribe/Decrypt messages
final Observable<RadixMessage> messageObservables = RadixMessaging.getInstance()
.getAllMessagesDecrypted(chatBotIdentity);
// Print messages
messageObservables.subscribe(System.out::println);
// Chatbot replies
messageObservables
.filter(message -> !message.getFrom().equals(address)) // Don't reply to ourselves!
.filter(message -> Math.abs(message.getTimestamp() - System.currentTimeMillis()) < 60000) // Only reply to recent messages
.flatMap((io.reactivex.functions.Function<RadixMessage, ObservableSource<AtomSubmissionUpdate>>) message ->
RadixMessaging.getInstance().sendMessage(chatBotAlgorithm.apply(message.getContent() + " from Bot!"), chatBotIdentity, message.getFrom())
).subscribe(System.out::println, Throwable::printStackTrace);
}
public static void main(String[] args) throws Exception {
ChatBot chatBot = new ChatBot(Function.identity());
System.out.println("Chatbot address: " + chatBot.address);
// Send message to bot
RadixIdentity oneTimeUseIdentity = new OneTimeUseIdentity();
RadixMessaging.getInstance()
.sendMessage("Hello World", oneTimeUseIdentity, chatBot.address)
.subscribe(System.out::println);
}
}
Running this will produce output similar to this:
Chatbot address: JGX2vijpLPBqTbtbznT81MGM7vVSDNDT95xHuChVdHnGzk9vBie
JGePib7zXBWa4ExNkpCmMbfkNy8H6UP351gMsdoYMgsrGUC43aB -> JGX2vijpLPBqTbtbznT81MGM7vVSDNDT95xHuChVdHnGzk9vBie: Hello World
JGX2vijpLPBqTbtbznT81MGM7vVSDNDT95xHuChVdHnGzk9vBie -> JGePib7zXBWa4ExNkpCmMbfkNy8H6UP351gMsdoYMgsrGUC43aB: Hello World from Bot!
Congratulations! You have now created a ChatBot connected to the Radix Network.
Join The Radix Community
Telegram for general chat
Discord for developers chat
Reddit for general discussion
Forum for technical discussion
Twitter for announcements
Email newsletter for weekly updates
Mail to hello@radixdlt.com for general enquiries
Top comments (0)