The last three months, I've been working on a grant given to me by Dfinity Internet Computer to work on SkyDocs. This report describes all the things I've worked on and includes links to more in depth information.

What is SkyDocs?

SkyDocs is a decentralized Google Docs alternative, originally build for Sia Skynet. It's written in C# with Blazor and compiled to WebAssembly.
It integrates with Sia Skynet for storage. Can use MetaMask for login and uses The Graph for document sharing.
For this grant, I will port SkyDocs to the Internet Computer.

What is Dfinity Internet Computer?

The Internet Computer is a decentralized platform that extends the internet. It's able to host frontend software and run backend code. It runs code in canisters and has provides an identity framework called Internet Identity.

The Internet Computer is the world’s first web-speed, internet-scale public blockchain. It enables smart contracts to securely serve interactive web content directly into the browsers of end users, making it possible to build dapps, DeFi, open internet services, and enterprise systems that are capable of operating at hyperscale. The Internet Computer uses smart contracts to power an emerging decentralized ecosystem of interoperable dapps and services, where nearly every system and service can run in reimagined form on public blockchain.

More info: https://dfinity.org/

Grant Goals

  • Hosting on the Internet Computer
    The current version of SkyDocs is hosted on Sia Skynet. For this grant, I also want to host SkyDocs natively on the Internet Computer.

  • Using Internet Identity
    For dApps running on the Internet Computer, using an Internet Identity as login is the standard. I'm going to add Internet Identity as a login method to SkyDocs. SkyDocs already supports username/password login and MetaMask login. After this grant there will be three ways to login.

  • Storing data on the internet computer
    I will be using the Internet Computer for storage of documents. There will be two storage options in the dApp.

  • Provide developer tooling for other .Net Blazor developers
    Once SkyDocs is running on the Internet Computer, I can make generic building blocks of the functionality I've build. So there will be a library for C# / Blazor developers that allows you to easily integrate login and storage on the Internet Computer.

  • Frontend improvements
    There is time left for frontend improvements. SkyDocs can use a UI overhaul by a frontend engineer.

Development and results

Beginning with the most visible results, Roelf-Jan, my colleague from Q42, has made some great changes to the UI.

New login

New editor

Hosting on the Internet Computer

The first step was getting to run SkyDocs on the Internet Computer. You need to understand how the Internet Computer works. It uses canisters to hold assets or smart contracts and you need Cycles so you can pay for the running of your canisters.

SkyDocs is published in an asset canister. It's published as a Blazor app which can run from any static file hosting solution.

Deployment was first done using the local command line tooling. After I got the basics working, I integrated a GitHub Action to auto deploy to the Internet Computer from GitHub.

More details about hosting and deploying SkyDocs can be found in this blog post: https://www.michielpost.nl/posts/hosting-skydocs-on-dfinity-internet-computer

Login and data storage

Adding the Internet Identity login to SkyDocs really made it feel like an Internet Computer app. The Internet Identity works with an authentication device, like a YubiKey. No username or password is needed.

The Internet Identity generates a new pseudonym for every dApp. This means, depending on the URL where you login, you get a different pseudonym/identity. This makes it secure, but you have to know and understand this behaviour. Because you will not get the same documents if you use SkyDocs on a different URL. And that might now be what you expect.

More information about the Internet Identity and pseudonyms can be found in this blog: https://www.michielpost.nl/posts/using-the-internet-identity-outside-the-internet-computer-ecosystem

Once you are authenticated, you can make authenticated calls to canisters. The canister will know your identity.

From Blazor to a Canister

How does it work? How does a Blazor WebAssembly app communicate with an Internet Computer canister?

C#

In our Blazor App, Icreated a DfinityService.c written in C# that knows how to invoke JavaScript. For example, this code invokes the setValueForUser JavaScript function:

 public ValueTask SetValueForUser(string key, string value)
        {
            return jsRuntime.InvokeVoidAsync("EntryPoint.setValueForUser", key, value);
        }

https://github.com/michielpost/Dfinity.Blazor/blob/master/src/Dfinity.Blazor/DfinityService.cs

TypeScript

The setValueForUser function is defined in the index.ts file:

export async function setValueForUser(key, value) {
  await storage_actor.insert(key, value);
}

https://github.com/michielpost/Dfinity.Blazor/blob/master/src/www/src/index.ts

It uses a storage actor that is created after login/authentication. The JavaScript storage actor knows the canister id of our storage canister.

The storage canister defines the insert method and stores the data:

publicshared(msg) func insert(name : Name, entry : Data): async () {
    let userId =Principal.toText(msg.caller);
     data.put(userId#name, entry);
  };

https://github.com/michielpost/Dfinity.Blazor/blob/master/src/storage/main.mo

All this code comes together when publishing using the dfx command line. It will generate 'declaration' files (.did) for your motoko canister. This declaration file can be used as import in your TypeScript/Javascript file:
import { _SERVICE } from "../../declarations/storage/storage.did";

And the index.ts TypeScript file will be transformed to minified JavaScript using the webpack build step.
This final index.js file must be included in the wwwroot folder of your Blazor app and can be called by the BlazorService.cs from C#.

Developer tooling

I've created Dfinity.Blazor as a seperate library. SkyDocs is using this library to provide the login and storage functionality. Other C# Blazor developers can also get this library from NuGet, use it in their app or contribute to the code on GitHub.

https://github.com/michielpost/Dfinity.Blazor

The installation process is not a one click NuGet install and you're done. More things are needed to properly use it. You also need to have a storage canister, and build the canister and JavaScript assets. The Dfinity build will wire up the correct canister ids in the minified JavaScript. If possible, I'll try to make the installation easier. For now, I've created a step by step guide in the readme file.

The library also comes with a sample app to get a quick demo of the included functionality: https://syisf-7qaaa-aaaah-aauda-cai.ic0.app/

What could be better?

To let the app store data, I had to develop a smart contract in Motoko. Motoko is a new language developed by Dfinity to write WebAssembly smart contracts. There are a lot of examples, but development is not easy. There is no easy way to debug your smart contract and support for unit testing is also in development. You can deploy to your local emulator, but it takes the speed out of your development process.
Of course this is being worked on and I have no doubt that there will be a better development experience soon.

.Net to native web assembly canisters

Instead of writing my smart contracts in Motoko, I would want to write them in C# / Blazor and export them to native WebAssembly. Unfortionately, this is not possible with .Net 5 or .Net 6. In the latest release of Blazor on .Net 6, there is a feature to import native WebAssembly components. But Blazor can't export to native WebAssembly, it's always wrapped and shipped with a .Net runtime.
Maybe in a next version we can publish to native webassembly? .Net 7? Let's hope so.

Custom domain name.

SkyDocs is currently hosted on this url: https://c3qag-6yaaa-aaaah-aaqta-cai.ic0.app/ That's not very easy to remember. There is currently no option to use a custom domain for your app.

Sia Skynet integrates with Handshake to host your dApp on a custom domain. This keeps it completely decentralized.

Dfinity is working on a solution for this problem, so we can use custom domains within the Dfinity ecosystem, but it's not available yet. When it is, you might see SkyDocs on the 'skydocs.ic0.app' domain.

What's next?

With the results from this grant, I hope other C# / Blazor developers will have some guidance to create a dApp on the Internet Computer. It's a great time to start experimenting with this new technology and see what's possible.

The Dfinity.Blazor library is open source and available on GitHub. It allows you to integrate login with Internet Identity in your Blazor WebAssembly app, even when your app is not running on the Internet Computer. This way, you can take small steps in porting your app.

SkyDocs has been working great as a testing dApp on different distributed platform. I think it will continue to do so. SkyDocs will stay as part of the Dfinity ecosystem and will be updated with new features of the Internet Computer when they become available.

References

SkyDocs on the Internet Computer
https://c3qag-6yaaa-aaaah-aaqta-cai.ic0.app/

SkyDocs on Sia Skynet
https://skydocs.hns.siasky.net/

Dfinity
https://dfinity.org

GitHub Projects

SkyDocs
https://github.com/michielpost/SkyDocs

Dfinity.Blazor
https://github.com/michielpost/Dfinity.Blazor