Exploring Tokens with Stellar

Creating a unique user experience for exchanging digital tokens

Overview

During the past few months, my team has been experimenting with how to simplify the process of issuing and managing asset-backed tokens. To accelerate our delivery schedule, we standardized on Stellar for the network and defined an experience around this platform. In this article, we will illustrate our usage of Stellar as well as demonstrate the client programming model using GraphQL and UI experience based upon React.

Author note: As a result of strong interest on this topic, we have released the source code on GitHub on March 14, 2019 under the organization token-factory.

Creating users

To start off, we wanted to first provide background on how Stellar manages account. Stellar describes the account process as

The noticeable gap here is around how to manage these accounts and how to associate users with accounts. To address this, we defined a simple user registry that grouped users by tenant and allowed some basic userid and password management. For enterprise use cases, this would quickly be replaced by an enterprise user management system such as LDAP.

Sign Up Page

Login Page

Improved approach to creating and managing accounts on Stellar

As mentioned in the previous section, an account consists of a public key and secret key. Since we wanted to associate Stellar accounts with users and also the management of these accounts, we enhanced the account creation to augment the account information with a description and a a passphrase. This allowed users to be able to quickly locate accounts based upon the description. The passphrase also simplifies the transaction process since users do not need to remember complex secret seeds associated with each Stellar account and can instead used the passphrase for signing of Stellar transactions.

Account Creation

For the user above, we have created a set of accounts representing various Actors in the system. Each of the accounts will be responsible for managing their own assets and also their account settings. The account settings are nested within each account and can be configured after the account has been created as follows.

Account Settings Page

Stellar provides various account management settings including setting thresholds for transactions and adding additional signers for the purpose of approving transactions or recovering lost accounts. These options are very common in financial transactions where institutions may require multiple signatures before approving transactions.

Creating Assets with context

The backbone of Stellar is the management of assets for a given account. Assets are the equivalent of currency that are used to make offers and payments within the Stellar network. In addition to maintaining the association of users and accounts, we also wanted to quickly be able to correlate asset ownership to users. For each Stellar account, we created an overview page that displayed the account balances and issuer of the asset. This asset page provides the real time view of account assets and balances.

Account Overview Page

In the account customer Todd account, we initially seed the account with 10,000 XLM (Lumens). This asset is used for making payments and handling fees for transactions for this account. In the above example, the customer Todd account owns to custom assets Gunther and Astro that can be used for offers and payments with other users in the system.

Making Payments

The simplest transaction for transferring assets to an account is payments. Payments are a unidirectional transaction where one account transfers an asset to another account. For custom assets, accounts need to trust the asset before receiving payment of an asset. The flow for trusting an asset is done via the Market assets view.

Market assets view

Once the trustline is established the account holding this asset can make payment to the trusting account based upon the amount the account owner has trusted.

Payment Page

Making Offers

Making offers in Stellar is really around bids and offers of assets where the network matches bids and asks for two assets. These transactions also require the same trustlines to be established with the main difference being the payments are bi-directional since two assets are being exchanged. The view for offers is similar to payments but enhanced to include the transferring of the two assets.

Once the offer has been accepted, the history view of the offers is updated as follows.

Offer History Page

Pending transactions

One of the gaps in Stellar today was the lack of visibility into pending transactions. As part of our implementation, we created a view for pending transactions that require action from the end user. The set of views are designed to be in the form of master detail where you can drill down into a given transaction to understand the current state of the transaction. In this example, the account has created an offer that is waiting on a matching offer.

Master Transactions Page

Master Detail Page

Adoption of GraphQL

From the outset of this project, we aligned our API strategy around GraphQL. GraphQL provided the foundation for a flexible and consumable data model that allowed our front end development team to quickly assemble the views that were demonstrated above. The API squad delivered GraphQL API docs as part of the CI/CD process that will be discussed in more detail below. With the powerful combination of the API docs and the GraphQL playground, front end developers can validate and test the APIs as part of the design process leading up to delivering the various views.

GraphQL Documentation

GraphQL Playground

Integrating with community APIs with GraphQL Stitching

Stellar is an amazing technology while at the same time emerging. As we were building out the platform, we tried to limit the amount we strayed from the various Stellar APIs and how much we persisted about tokens in our local databases. One of our key finds was the existence of a 3rd party GraphQL endpoint called https://core-test.gly.sh/graphql that exposed GraphQL APIs for the various Stellar Schema objects on the test network. We decided to leverage these APIs for the various queries (READ APIs) which reduced our overhead on writing custom APIs for data that was stored inside of the Stellar Network but was not accessible via the Stellar SDK. This work truly validated our decision to use GraphQL since GraphQL stitching enabled us to exploit multiple GraphQL providers/endpoints while maintaining a single API endpoint for our front end developers to consume.

Testing with standalone Stellar Node

One of the tenets for our testing was to limit dependencies and things that could fail during testing such as network connectivity. When we delved into testing our Stellar GraphQL APIs, we occasionally hit network hiccups or latency due to rate limiting on the test network. To address this, we decided to deploy the community Stellar docker image as part of our CI/CD process. This greatly reduced our surface areas for exposure as each build deployed a local instances of the Stellar standalone node and discarded the node when testing was complete. This ensured that we had a clean environment on each test run and also provided the stability that we needed. In our Make script, the standing up the node was actually as simple as…

stellar-quickstart:

docker pull stellar/quickstart

docker run — rm -d -p “127.0.0.1:8000:8000” — name stellar stellar/quickstart — standalone

Approach to CI/CD using GitOps and Helm

When we started on this project, we standardized on Kubernetes for hosting our workload. The choice of Kubernetes was obvious as we wanted to be support a variety of deployment targets and also abstract the target environments we deployed to. To achieve squad autonomy and maintain velocity for each squad, we prescribed a model where we separated out code projects from deployment projects. Each micro service was responsible for building, testing and publishing Docker images for their service. When there was a successful build, the build triggered a PR against the deployer project for that service.

The deployer project is one that is gaining steam in the GitOps community. With the model of configuration as code already being while adopted for things such as Ansible, GitOps is taking the next step as a ways to accelerate deployments with clear audit trail and observability of live deployments.

In our project, we use Helm to orchestrate our K8 deployments. Our Helm Charts are managed in Git in our deployment repo. When the build is successful for a given code repo, a PR is automatically generated against the deployment repo to update the image tag for the component that was just updated. This PR is then auto-merged which triggers a deployment of the Helm chart to our Kubernetes either our test or demo environments based upon the flag. This provides the team with a history of our deployments that map directly to our git repos commit history to aid in debugging in the case of failures or regressions.

Conclusion

In the article, we discussed some of the approaches we took to simplify building and deploying Stellar on Kubernetes. We found Stellar to be feature rich and only felt compelled to extend Stellar in a few areas to improve the overall user experience around the token lifecycle. If you are looking to deliver a token based solution, we hope that you learn from some of our ideas that we explored in this article.