Algochat — A Public Chat on Algorand TestNet
Today Algorand TestNet became public, so now anyone can join and safely start getting hands dirty since this is the test chain.
To start, you can jump right into the Developer documentation which has step-by-step explanations to install an Algorand node and information about the node CLI interface.
I think the documentation it’s pretty clear on node installation, CLI and REST/SDK utilization but if you have any question, you can jump into Discourse where the growing community can help you with any problems. Finally, consider reading the Developer FAQ that may answer some important questions too.
What can be done on the TestNet?
At the moment, the main capabilities of Algorand are native token transfers named Algos. After you create your wallet and accounts, you can ask for free Algos in the Algorand TestNet dispenser.
The Algorand project has a cryptographically committed roadmap which might unveil some surprises in the future. Despite not knowing everything coming up, there are some definite features on the way such as Smart² Contracts, Governance within the chain, dutch-auctions, and more.
While reading the developer documentation, I noticed that the command
goal clerk send had a
-n flag to include a plain-text message with the transaction. For example, you can transfer 10 Algos to a friend and include the reason for it.
But, there’s another, more interesting flag
-noteb64, which is a URL-base64 encoded string. As a developer who’s been around the blockchain space for some time, I immediately thought of the obvious: how about using the note field to save arbitrary data for a Layer 2 dapp?
TestNet + Go SDK + note field = ?
Before I tell you more about the dapp PoC, we should consider an important fact.
The note field can hold arbitrary data, but transaction validity doesn’t depend on it. So don’t rush to thinking we’re talking about smart contracts that ensure valid state.
Using the note field this way implies a Layer 2 application consider data on each transaction to be possibly invalid, just because it could be total garbage or because it tries to do an invalid state transition considering the actual state of the dapp.
Going a step further, this isn’t that bad because anyone running the dapp will conclude the same. Even if the blocks have invalid transaction data, after processing each block nodes will have the same state.
Back to our initial topic: let’s focus on the note field to encode arbitrary data.
I thought about multiple ideas of a dapp taking advantage of the note field. After considering various options, I opted for doing a simple public chat. Anyone with an account could send messages to the chatroom, and anyone could see them. Since the messages live on-chain, they’re non-repudiable, censorship-resistant, and immutable (properties ideally we get for free by a good blockchain).
Some more interesting ideas also were on the table, but the state of the dapp was a bigger challenge. To solve those challenges, I started coming to the same conclusions used in other blockchains, cryptographic state commitment on-chain like Merkle trees and proofs.
Favoring less complexity, a public chat room was less demanding of safely handling state. Also, my original time constraints involved a weekend so, finally, I committed to it.
The source code of the dapp and step-by-step installation instructions can be found here. Besides me taking attribution to choose Algochat name, this isn’t an official application nor a suggested way of using the SDK, just a PoC.
The application has two main modules, the UI and the message stream. Both modules communicate by using three golang channels:
- The in channel: every time message stream module detects a new block, thus eventually new chat messages, it send them to this channel. On the other end, the UI is reading the channel to show the messages in the UI.
- The out channel: Every time the user writes a new message through the UI, it gets passed in this channel where the message stream module takes it. Then, a new transaction is built encoding the message in a structure marshaled in JSON. The note field of the transaction contains the byte representation of it.
- The logg channel: This channel is similar to the in channel regarding what goes there is shown on the UI but on a special Log section. The purpose is to explain to the user what’s happening behind the scenes.
If you run with the
-h flag you can understand what you should configure:
$ go run main.go -h
Usage of main:
algod.net address (default "http://localhost:8080")
the addr of the wallet from which you will pay the txn fees
kmd.net address (default "http://localhost:7833")
username to use in the chat (default "Guest")
the name of the wallet to use
the password of the wallet
Your node and kmd service should be running (
goal node start and
goal kmd start). In the data folder, you’ll find algod.token and algod.net with the authentication key and endpoint of the node respectively. In the data/kmd* folder you’ll find similar information to run the app.
$ go run main.go -wallet funnywallet -walletpassword funnypassword123 -from <from-addr-from-your-wallet> -algodtoken <algod.token> -kmdtoken <kmd.token> -username bobgorand
Details about the implementation
Here’s a bullet list about some decisions and application mechanics:
- Whenever a user sends a message to the chatroom, it gets marshaled in the note field of the transaction.
- Every transaction with the destination address KPLD4GPZYXST7S2ALYSAVRCBWYBCUQCN6T4N6HAYCHCP4GOV7KWJUGITBE is considered a message of the app.
- Every message also shows the first 5 sringified characters of the address that sent the message as a prefix of the username.
- The message is JSON encoded. Considering the note field size limitation, a more efficient encoding like protobufs would be more convenient.
- The transaction corresponding to each message sends 0 Algos to the chat address and uses the suggested fee from the SDK.
- When you open the chat it will show the messages contained in the last 1000 blocks. Originally I wanted this to be parameterizable, but since the default node is non-archival it doesn’t make much sense. 1000 blocks ~ 1-hour approx.
- The SDK allows sending the transaction only asynchronously. After the transaction is submitted, the program scans the pending transactions until the sent transactionID is out of the pool, then considers the transaction confirmed (not 100% true, PoC assumption :).
- Ctrl+C will close the program immediately. The code doesn’t worry about finishing goroutines gracefully.
- Everything you see in the Algorand Chat window is exclusively confirmed on-chain. I intentionally avoided cheating showing new messages as soon as is submitted (before real confirmation). In a production chat service, we’d intentionally do the opposite, display it right away with some UX signals (async).
Points of improvement
Here I described a funny project that I did to try the Go SDK to do something different on the TestNet that transferring Algos.
The most important part of the code is reprocessing the last 1000 blocks and listening to new ones. The rest is just boilerplate to UI, SDK initialization and sending events through channels.
Regarding being notified of new blocks, it would be nice to have this feature natively supported in the SDK since I think it would be, most of the time, needed in most use cases of the SDK.
Additionally, a cleaner way to the transaction confirmation phase would be nice too since multiple things can fail. The transaction might be rejected from the pool of pending transactions because some field is invalid or the account balance isn’t enough. If that went correctly, there could be a problem while waiting to be included in the next proposed block or with its final confirmation.
The SDK can help the developer to provide synchronous ways of sending transaction until full confirmation/error, or asynchronous with callbacks/events channels.
The bottom line is, joining the TestNet and using the SDK is straightforward. It might have points of improvement by the project is releasing its first public version.
Regarding the application, it was pretty fun to use the TestNet to a more general application compared to simple token transfers. As with sending Algos with the command
goal clerk send, you can appreciate fast transaction confirmations.
I’m very curious to see Algorand’s future capabilities, not only in the SDK or features of the blockchain but also the behind-the-scenes technology which is super-interesting. If you’re into understanding the inner-gearing of Algorand, you can find white papers in the Algorand official website, articles on the official Algorand channel, and also in my Medium account too. For example, my last article was about trying to gain intuition behind some cool stuff about Algorand.