This is largely an opinion piece focused on the EOSIO Reference Authenticator, UAL, and the tooling surrounding these projects. All were created with great intentions, but the execution didn’t work out.
It’s been a long while since I have looked at the reference authenticator, but from what I remember: the payload specification wasn’t going to work well (it was all hex encoded JSON, and a lot of it), the eosio.assert
contract was very cumbersome (both on-chain and for the APIs/wallets), and the manifest specification (while nice and related to the conversations today in Telegram) had many quirks. The SDKs (Swift and Java) used in the reference authenticator, while not directly related, were also heavily opinionated by the choices made within the other components listed above.
UAL on the other hand survived and has seen some adoption. I think that’s largely because the reference authenticator was abstracted away from it enough and other wallets could build plugins for it. As soon as a second active protocol emerged (ESR/Anchor coming in to a Scatter/protocol dominated market) that need was realized. The execution on UAL is ended up in a similar situation as the authenticator itself, and I wrote details about the shortcomings of UAL in this thread and touch on it briefly when posting about whether developers should be using a wallet abstraction library or not.
We have put a lot of effort into our SDKs, which integrate into UAL, and now see areas where some components should be elevated out of Anchor-specific code and into wallet-agnostic code for others to use - the newest of those being Resource Providers. This is incredibly hard with how UAL was initially designed since the interfaces themselves are what need to change. That’ll require redoing everything most likely and at that point, it might as well be a project built from scratch and reimagined for todays needs.
To get even further in the tool chain - UAL is based on eosjs which brings along another set of limitations. UAL operations largely depends on how eosjs functions… which is basically a black box. You push in A to a function and you get B in response. There’s no room for interpretation in how the code goes from A to B, which is a problem when you want to go from A (create transaction) to C (cosign transaction) to B (sign transaction). There are many instances where this same situation plays out while using eosjs and it’s not possible to deal with unless you copy chunks of the eosjs code and reimplementing it in your application.
From top to bottom the components in this stack had design problems. Seeing as how we’re on the frontier of technology, this isn’t unexpected and should almost always be expected. The problem however was that B1 (as the creator of these libraries) didn’t identify these problems in the design and we (the community of developers) hadn’t yet experienced the issues to help shape it. As an outsider, I can only imagine this was not the developers fault but instead the general nature of priorities within a company. However, with how interconnected all of these components were, it ended up being very hard to affect change without breaking other things, leading to a situation where the community really couldn’t make much use of these things.
A new generation of tooling
So with the history outlined and some of the problems touched upon, this is where I’m going to start talking more about what our team has been doing for the past two years related to this, and hopefully illustrate the importance of this effort. Right now I am more interested in getting other developers engaged than shilling our work, but it’s probably going to sound like shilling.
So starting with the authenticator and its related components… everything used in the authenticator was depended on one another, the payload spec required the assert contract, the manifest spec, and even the SDKs to some degree. You couldn’t use the authenticators approach unless you accepted all of the components and each of their individual pros and cons. We believed the cons of the entire stack outweighed the pros of using any individual piece, and the changing any individual piece required changing multiple parts of the stack.
So we started our approach by creating individual components that didn’t depend on one another. This is where the EOSIO Signing Request proposal (EEP-7) (ESR) came into play serving as the basic building block that defined a transaction. The payloads from ESR are encoded using the same ABI encoding techniques the blockchain uses, which solves many issues with size and compatibility that the reference authenticators protocols would have run into. It also cuts out all of the excess data, that while useful for some requests, don’t need to be required by all requests. Instead it allows those extra components to exist without rigidly requiring them.
As for the reference authenticator app itself, the reference authenticator was a UI built on a specific payload/assert/manifest spec, so it wasn’t really reusable. We started prototyping Anchor mobile, heavily inspired by the reference authenticator’s approach, but changing the internals to use ESR. For our iOS prototype, this also led us to implement the ESR specification in Swift, and while we were at it we wrote our own library to handle everything Swift related and ditch the B1 library. We stopped using the B1 library for the same type of reasons I outlined above related to eosjs, it’s difficult to use and serves mostly as a black box.
Anchor at this point could now take in an ESR payload and sign a transaction. The difficulty though was getting the transaction payload from an application to the signer - which led to the creation of another protocol on top of ESR, the Anchor Link protocol (which should have a more generic name since it’s capable of more than just supporting Anchor … but it has stuck). This is another building block, one which is capable of establishing a session between an ESR compatible authenticator and an external ESR compatible app/dapp.
If it breaks down or is unavailable, the ESR payload with an ESR authenticator still works - it’s just not as easy to send them from point A to point B (you need a URI handler or QR code or something). It also introduced encryption, identity requests to serve as a handshake mechanism, and a number of other convenience features that help improve the user and developer experience.
It’s also completely replaceable - someone could take the ESR specification and build an entirely different way of relaying the requests without how we designed Link or the transport.
Anchor Link was also intentionally designed to accept modular transports, allowing the creation of different user interfaces and ways to use these sessions. We created the first one we just generically called the browser transport. This transport is what we plug in to wallet abstraction layers like UAL or Transit to provide the experience users experience today. This is also where we have integrated Fuel to provide both free and paid transactions to the end user of an application, though this logic should realistically exist in the wallet abstractions themselves.
In developing both Anchor Link, the transport, and the plugins to distribute this tech - that’s when we hit the wall with eosjs. So just like we did with Swift, we built a powerful javascript library that serves as a replacement for the B1 code that we simply call @greymass/eosio (and sometimes refer to as eosio-core
). This library serves as another stand alone building block, which now Anchor Link and the transport are based upon (along with a lot of other projects). It allows us as developers to overcome the challenges we experienced much more easily and allows us to do things that just aren’t possible with eosjs.
Today
It’s been a couple years now and despite all this effort there’s still a lot more to do. Just based on what was described above, I can easily rattle off a few issues discussed above that we haven’t touched yet:
- The problems that the manifest/assert components originally tried to solve still haven’t been resolved yet. We have some ideas, which were the ones that sparked this entire conversation in Telegram.
- UAL hasn’t been improved upon and has severe limitations on how it can be used. This is an area I’d really like to tackle since I think we have some great experience and insight working with Anchor Link and the transport - but there’s little incentive to do so.
- The Java SDK from B1 has many of the issues that the Swift SDK from B1 did. We have a replacement for the Swift SDK, but no replacement for the Java one. It would be worthwhile to revisit and redevelop it for Java developers using EOSIO.
- Some of the new solutions presented above are not complete and many have no real documentation, so its hard for other developers to adopt them. This again is largely due to prioritization issues and lack of hands on keyboards to generate it.
The future is bright though, and I really believe what we have started and continued working on, and would like to get others working on with us, is the start of the EOSIO 2.0 application stack. The EOSIO 2.0 backend launched a while back and had significant improvements, and the backend keeps improving - but the application side of the equation as it is presented to developers today is very rough around the edges.
Things like ESR, the Link protocol, transports, the JS/Swift/Java SDKs, a UAL replacement library, and clear documentation around all of it are what EOSIO development is going to look like in the future.