TipALPH: a tipping bot for Alephium

TipALPH: a tipping bot for Alephium

Ā·

7 min read

We participated to the Alephium Hackathon that took place in February 2024. As part of this event, we developed... TipALPH šŸ„³

As you may infer from its name, TipALPH has to do with tips (of money or crypto-currencies in this case) and the Alephium blockchain.

More precisely, our goal was to create a simple and very intuitive bot to enable users to tip each other $ALPH, the main currency on the Alephium Blockchain. Similar to the LightningTipBot for Lightning, available on Telegram. Once this first step was functional we worked on supporting the other tokens of the Alephium blockchain, such as the $ALF or the $AYIN.

In this article, we will detail the process we went through, how the code is structured and the future steps for TipALPH.

Warning: some of the code that is displayed and linked in this article refers to the first functional version of TipALPH. Additional features have been added since, complexifying the code. This is why we present this simpler version here.
Let us know if you would be interested in reading about the development of the added features!

Design & implications

As mentioned, we wanted a very simple and intuitive bot. Users should be able to seamlessly initiate a chat with the bot and then directly receive and send $ALPH.

This tends to a custodial solution, where the bot handles the private key related to the users account on behalf of the user. The other option, using a non-custodial wallet, would require users to connect an external wallet and to approve each tip, which makes it a lot harder to use and restrict user adoption.

This choice implies that users should be able to deposit to and withdraw from their managed accounts. Since they do not know the private key related to their accounts, we strongly advise users not to let too much funds on their accounts. Hopefully, they should not do so as the goal is to send tips to other users, not yearly salaries.

Considering this design decision, the bot will have a wallet with a mnemonic that we keep very secretly. From this wallet, we would derive an address for each user, upon registration. This address would hold the funds for this user.

The basics commands that should be available to the users are:

  • /start to initiate an account with the bot

  • /tip to send tips to other users. We want that this command could used with an amount and a Telegram username in a chat but also with a number, in reply to another user's message (which will receive the tip)

  • /address to display the user wallet address to enable user to deposit funds to their account and to view their account transactions on the explorer (for transparency)

  • /balance to see the user account's balance

  • /withdraw to retrieve funds from the managed account to a external accounts. This command will require the amount to withdraw and a destination address

A /help command, displaying information about the commands and the bot behavior would also be desirable.

Now that we defined what we want, let's see how we can implement it!

Technology choices

Our bot will need to communicate with an Alephium Fullnode to access the blockchain status and send transactions to it. We will have our own fullnode, to ensure availability, running from a docker compose (instructions for it can be found here). Moreover, we also would like to have a library to easily create a Telegram bot. These are the two major constraints that will lead the language selection.

While we LOVE Golang, we decided to use Typescript and make use of Alephium's convenient Web3 SDK since it really facilitates the use of the fullnode. Moreover, there is plenty of code examples of how to connect to the blockchain and interact with smart contracts with the Alephium Web3 SDK in their documentation and in their Github repository (including a starting point for a tipping bot).
A popular JavaScript library for developing Telegram Bots is Telegraf.js, so we decided to give it a try, complementing it with the @telegraf/types module to have the type annotations for Typescript.
For simplicity, we fixed the Node.js version to lts/hydrogen (v18.19.0).

We will package the application in a Docker image for ease of deployment and upgrade.

To keep track of which user is registered and their respective derivation path to have access to their address, we will need a database. Being huge fans of easy-to-deploy-and-maintain SQLite databases, we will rely on one to store what we need.

Data and database structure

Being deeply concerned about the privacy issues, we apply the data minimization principle and only collect and store data that is required for the application to perform what is expected.

Thus we only store, upon user registration, their Telegram username since other users might use it to tip them, as well as their unique Telegram identifier. We associate to these two elements, a unique identifier, that is used as derivation path to derive the user address from the bot wallet. Since each user id is unique, there's no risk of a user sharing an address with someone else.

To summarize, we store User(id, telegramId, telegramUsername) . This User object is available and used in the code, as you will see in the code example below.

Code structure

The code is split in two main parts 1 : an Alephium client, that makes use of the Web3 SDK to propagate instructions into the blockchain, and a Telegram bot file to instantiate the bot, define the various commands available and call the alephium client on it. We will explain them more in details below.
Of course, we have a starting point, utilities and configuration files, but these are less interesting to detail in a blog post. šŸ˜‰

Telegram bot

The main part (meaning the code from which the application is started) instantiate a Telegram bot class and provide the necessary elements for it to operate (Telegram bot token, connection to DB,...). The commands listed above can be defined to perform the expected action, using the database to keep track of new users and their addresses, and the alephium client below for interacting with the blockchain.

For instance, the /tip command can be summarized to:

bot.on("/tip", async (ctx: Context<Typegram.Update.MessageUpdate>) => {
  // Retrieve the sender of the tip
  const sender = await db.getUserFromTgId(ctx.message.from.id);

  // We extract the amount and receiver of the tip from the message
  // ...using regex ;)
  const args = tipAmountUserRegex.exec(ctx.message.text);
  { amount, receiverUsername } = args.groups;
  const receiver = await db.getUserFromTgUsername(receiverUsername);

   // We use the alephium client to perform the transaction on the chain
  const txId = alphClient.transferFromUserToUser(sender, receiver, amount);
  ctx.sendMessage(`Tip successfull! TxId is {txId}`);
});

The original and complete code can be found here.

Of course, we do a lot more than this! This only works if you mention the receiver in your message (e.g. /tip 1 @jane_doe). We did not mentioned all the required verifications (are provided arguments valid? is sender registered? does the receiver exists? are they also registered? do need to register them before? ...).

Alephium client

In this file, we create the link with the alephium fullnode and provide functions to perform some actions on the blockchain (transfer fund, consolidate UTXOs,...).

For instance, the transferFromUserToUser function used above could be summarized as:

async transferFromUserToUser(sender: User, receiver: User, amount: string): Promise<string> {
  const senderWallet = this.getUserWallet(sender);

  const newTxId = await senderWallet.signAndSubmitTransferTx({
    signerAddress: (await senderWallet.getSelectedAccount()).address,
    destinations: [{
      address: receiver.address,
      attoAlphAmount: convertAlphAmountWithDecimals(amount), // From SDK
    }]
  })
  .then(tx => tx.txId)
  .catch((err) => Promise.reject(this.handleError(err)));

  await waitTxConfirmed(this.nodeProvider, newTxId, NB_CONFIRMATIONS, 1000);

  return newTxId;
}

The original and complete code can be found here.

Conclusion

We showed the process we went through to develop TipALPH, as well as some code that makes the /tip commands (all the other commands are simpler or similar anyway).

Since the initial release of TipALPH, we added support for the other tokens on the Alephium ecosystems (such as $ALF, $AYIN or $JURA) and greatly improved the messages displayed by TipALPH.

As future steps, we would like to enable TipALPH users to directly interact with dApps (such as Ayin) and to expand the bot to Discord as well.
If you know Typescript and would like to help, we could use your help for some issues we are facing. Do not hesitate to get in touch!


  1. For now, each part is in a single dedicated file, which is not really modular and is not handy with the addition of new features, resulting in large files. We will re-structure the code and split each of these parts in multiple files for easier management. ā†©

Ā