Introducing Dedot: A delightful JavaScript client for Polkadot & Substrate-based blockchains

We are thrilled to introduce Dedot, the next-generation JavaScript client for Polkadot and Substrate-based blockchains. Designed to elevate the dapp development experience, Dedot is rebuilt from the ground up to be lightweight and tree-shakable, offering precise Types and APIs suggestions for individual Substrate-based blockchains and ink! Smart Contracts. Dedot also helps dapps efficiently connect to multiple chains simultaneously as we head toward a seamless multi-chain future.

Overview

Dapps have always been a crucial part of any blockchain ecosystem, providing users with a means to connect and interact with blockchain networks. Given the complex nature of interacting with Substrate-based blockchains, developers need to focus on business logic rather than connection intricacies. Thus, a middle layer between dapps and blockchain nodes to facilitate these connections and interactions is essential.

@polkadot/api (pjs) has been widely adopted and integrated into most dapps within the ecosystem. It has effectively simplified the process of connecting applications to networks by abstracting the complexities of interacting with Substrate-based blockchains and handling the scale-codec serialization process.

However, through our development experience, benchmarking, and profiling, we discovered that @polkadot/api has several limitations that may hinder developers from creating optimal dapps for the Polkadot ecosystem.

Limitations of Polkadot.js API (@polkadot/api or pjs)

Large bundle-size (wasm & bn.js & unused type defs)

I believe any developer using @polkadot/api to build their dapps will recognize this issue firsthand. @polkadot/api has tight dependencies on wasm-blob (crypto utilities) and bn.js for handling BigInt numbers. Additionally, it comes with a large number of type defs by default, even if the dapp doesn’t use most of those APIs or information. This makes the entire bundle size of dapps quite large, resulting in a poor user experience as users have to wait longer before they can start interacting with the dapp.

Here is the bundle size of a very simple dapp built using @polkadot/api (with no other dependencies) that performs two relatively trivial steps: 1) initializing the API instance, and 2) fetching the account balance. As shown in the image below, the pre-compression size is close to 1MB, and even after gzip compression, the size remains quite large for such a simple dapp.

High memory consumption

This is the issue that wallet providers or any dapps that need to connect to a large amount of networks at the same time might get into. For example, connecting to 100 RPC endpoints at the same time can potentially consume around 800MB of memory. Through benchmarking and profiling, we’ve pinpointed the root cause of this issue, long story short: its type system. We have a very detailed benchmarking and analysis in the proposal to Web 3 Foundation Grants Program to build dedot (formerly named DelightfulDOT) almost a year ago.

As we’re heading toward a multi-chain future, we believe the ability to connecting to multiple blockchain networks at the same time efficiently and effectively is very important.

Limitations in Types & APIs suggestions for individual chains

@polkadot/api only comes with a default types & apis suggestions for only Polkadot & Kusama. This creates a very bad DX especially for new developers working on parachains or solochains with different business logic coming from different pallets & runtime apis.

I remembered my first time working with @polkadot/api to interact with my custom substrate blockchain. I was having a really hard time to define custom runtime-api typedefs and figure out which api to call in order to interact with my pallet (extrinsics & storage). I was also struggled on how to construct a struct, a tuple or especially an enum to pass those as parameters into the api. Give me a thump up if you are also in my situation the first time working with @polkadot/api. :slight_smile:

Dedot comes to address those issues

Small bundle-size and tree-shakable

Dedot was rebuilt from scratch to avoid the pitfalls faced by @polkadot/api like type defs system (thanks god! we have metadata v14 & v15). We eliminated dependencies on wasm-blob and now use the native BigInt primitive instead of relying on bn.js.

As a result, the same dead simple dapp that has the size of nearly ~1MB built with @polkadot/api earlier, now the size is down to 127kB (gzip: 39kB) with dedot. It’s ~7-8x smaller. Don’t trust my number, verify it yourself!

Less memory consumption

dedot’s type system are relying completely on native TypeScript/JavaScript types, and with the help of subshape for scale-codec encoding/decoding. This makes dedot to use memory more efficient in parsing and handling big raw metadata blob.

We’re also seeing significant improvement in memory consumption when connecting dedot to multiple networks at the same time. Detailed benchmarking & comparison between dedot and @polkadot/api can be found here. You can also run the benchmarking script yourself to verify the result. TL.DR: ~4-5x less memory consumption compared to @polkadot/api.

In an attempt to verify how much impact dedot could make in term of memory consumption in a real-world application. I was trying to integrate dedot into SubWallet, a leading wallet in Polkadot ecosystem. When turning on connections to all of the Substrate-based networks SubWallet supported (+100 networks), SubWallet running dedot was consuming less than a half the total memory consumption when it’s running with @polkadot/api. While the result’s much less compared to the raw benchmarking (since there’re a lot of other things can could impact memory consumption in a real application), this shows that we can build lightweight wallets or applications that connect to hundred of network connections at the same time efficiently with further optimizations.

Types & APIs suggestion/auto-complete for individual Substrate-based chains.

With the latest changes in metadata v14 and v15. We can now have access to most of the available types & APIs that’s exposed by the runtime. We were able to convert/generate those Types & APIs information encoded inside the metadata into plain TypeScript Types & APIs. So dapp developers can now being aware of all available Types & APIs for any particular Substrate-based blockchain that they’re working on. E.g for Polkadot runtime: types, tx, runtime-apis, storage queries, constants, …

We’re maintaining a package named @dedot/chaintypes with a goal to maintaining Types & APIs for all of Substrate-based blockchains in the ecosystem. So dapp developers can just install the package and pick which ever the ChainApi that they want to interact with.

Below is an example of how to interacting with different chain apis with ChainApi with dedot:

chaintypes

Currently, there is a scheduled job running twice everyday to check if there’s any runtime upgrades in the supported networks and regenerate the Types & APIs for those networks. So developers just need to upgrade this package everytime there is a runtime upgrade to be exposed to latest runtime changes. E.g: recently there is a runtime change in Kusama to remove the Identity & IdentityMigrator pallets, this change is then get updated for Kusana chaintypes swiftly.

Dedot also comes with more & more features

Native TypeScript type system for scale-codec

Instead of using a wrapped codec (e.g: u16, u64) in @polkadot/api, dedot directly use TypeScript type system to represent these types (e.g: number or bigint).

This make it easier for new dapp developers get started as they don’t have to unwrap the codec (.toNumber(), .toBigint(), …) to access the data. Also downstream libraries can easily inspect and utilize the types defined for suggestion & type-check.

Adopted latest changes in metadata V14 & V15

dedot creates types dynamically lazily on the fly with information from metadata and the types will be used for scale-codec encoding & decoding data.

An important change in metadata V15 is Runtime APIs information. dedot do leverage these information to expose the APIs (eg: Polkadot) & make the call.

dedot also supports metadata V14 for chains that haven’t upgraded to V15 yet OR you simply want to query/access historical state where only V14 is supported. dedot also comes with explicit Runtime API specs so you can call Runtime APIs with metadata V14 as well.

Build on top of new JSON-RPC specs (and the legacy as well but deprecated soon)

The new JSON-RPC spec is the new standard and is encouraged to use. dedot is also using these new apis by default.

For the chain that haven’t upgraded the the new spec yet, dapps could still be able to connect with those chains via a LegacyClient that’s built on top of the legacy JSON-RPC APIs. But this will be deprecated soon in favor of the new spec.

Support light clients (smoldot)

Since smoldot has a very good supports for new JSON-RPC spec for better performance. Developers can connect to the network via smoldot light client using the SmoldotProvider.

Typed Contract APIs

Another limitations of @polkadot/api is lack of types & apis suggestions when working with ink! Smart Contracts. With dedot, we’re going to change this forever. Similar to how we expose Types & APIs from the runtime metadata, we’re using the same trick for ink! smart contracts as well to enable Types & APIs suggestions for any ink! contracts that you’re working on.

Below is quick gif to show you how does it look when you works with a PSP22 smart contract. Or if you want to see a working example, here’s the code. There is more improvements and refinements to do for the Contract APIs, but it’s ready for you to explore and play around now.

typink

Fully typed low level JSON-RPC client

This is useful for advanced users who wants to interact with the node directly via JSON-RPC call without having to go through the whole bootstrapping of downloading metadata or following the chain head.

A builtin mechanism to cache metadata

Downloading a big metadata blob can take a large amount of time, depending on the JSON-RPC server that dapps are connecting to, it might potentially take longer if the connection is via a light client. For example, downloading Polkadot metadata (~500 kB) can take up to 500ms or ~1s or even longer depends on the network conditions.

This is a nice to have feature where dapp only have to download metadata on the first load, later metadata can be fetched directly from cache without having to download again (until there is a runtime upgrade).

Compact Metadata (on the road-map)

Most of dapps do not use all of the Types and APIs from the metadata, so why not extract only the information/types that dapps needs to function properly. Our goal is to produce a small and compact metadata that can be easily bundled inside dapps, so dapps no longer need to download metadata again from the network directly (until the next runtime upgrade), saving a reasonable amount of loading time. (ref)

XCM utilities (on the road-map)

Crafting an XCM are a bit complicated, due to the heavy usage of nested enums. Developers can still making an XCM transaction with dedot by following along with the types suggestions. But the syntax is very cumbersome and inefficient. We plan to add some extra tool on top to help the process of crafting XCM message easier.

React Native supports (on the road-map)

Supporting React Native can encourage developers to build mobile applications on Polkadot, broadening the range of applications within the ecosystem.

And a lot more toolings around dedot to come

Migration from @polkadot/api to dedot

dedot is not designed to be drop-in replacement for @polkadot/api, but we make some intentional decisions to help the migration process from @polkadot/api to dedot a lot easier and faster. You should already see some familiarities in api styling between dedot & @polkadot/api. More information about migration can be found here.

What’s next

Dedot is currently in alpha testing phase, so it’s ready for your experiments and explorations. We’re expecting some more breaking changes before stabilization. Here a few places that we want to continue to optimize and adding further improvements:

  • Futher optimize JSON-RPC v2 integration
  • Continue Contracts APIs
  • Improve @dedot/chaintypes package and supports more networks
  • Improve smoldot integration (add known chain specs, worker helper)
  • Documentations & example dapps
  • And a lot more on the road map to help building a fully-fledge client.

Who we are?

We are small team that falls in love with Polkadot technology and believe in the vision of a decentralization future.

  • We’ve started contributing from 2022 and since then we have secured 2 W3F Grants to building open source for Polkadot:
    • The 1st grant is to build Coong Wallet, a website-based wallet that’s compatible with @polkadot/extension APIs and works seamlessly on both desktop and mobile.
    • The 2nd grant is to fund the initial phase of dedot (formerly named DelightfulDOT)
  • We’re also the 1st prize winner of Polkadot Hackathon Vietnam 2023 with InSpace, an on-chain community launcher via ink! smart contracts.
  • Thang (@sinzii), our lead developer, is a PBA 5 graduate in Singapore.

We need your feedback and supports

We can’t build this alone without community feedback and support. We would greatly appreciate it if you could give dedot a try and let us know what you like or dislike about it.

Aside from the initial funding from the W3F Grants Program, we’ve been self-funding dedot to work on some crucial integrations, such as the new JSON-RPC specs or Typed Contracts APIs, … We’re now seeking for community feedback and asking for funding from the treasury to continue the development of dedot to bring the dapps development DX of Polkadot ecosystem to the next level. We hope to have your all supports. Thank you very much!

Please let us know if you have any feedback by respond to this thread or post a discussion, raise an issue in the dedot repository

We’d love to connect everyone as well

21 Likes

cool tool, thank you so much

1 Like

Thank you @HongThaiPham, really appreciate your support! :grin:

This is great work @sinzii :raised_hands:

Typescript type conversion was quite necessary, people used to get lost figuring out the typings. (Including me)

1 Like

Thank you @itsyogesh! :partying_face:

Typescript type conversion was quite necessary, people used to get lost figuring out the typings. (Including me)

Exactly, I also in that situation when I first started with Polkadot and I believe many others are experiencing the same. This is also quite painful for new developers in the ecosystem as well. :smiling_face_with_tear:

Nice job, mate; I will definitely use it in our next project.

1 Like

Hey @leonardocustodio, thank you so much for your support! :star_struck:

Please do let me know if you have any questions or run into any issues while trying out dedot. I really appreciate it! :pray:

Hello everyone,

Today, we’ve put forward a treasury proposal to ask for funding support from the community to continue the development of Dedot. We hope to have your support on this journey of improving developer experience for Polkadot ecosystem.


We’ve also put together a demo dapp at https://try.dedot.dev (source-code) to showcase dedot features & functionalities:

  • You can connect to networks via RPC Node or Light Client (smoldot), and via the new or legacy JSON-RPC APIs.
  • You can also open the dapp and interact with networks on mobile phone with the support of Coong Wallet. Make sure to open the dapp on a native browse app (Chrome, Safari or Firefox), in-app browser might not work as expected.
  • There’re more working example code on dedot repository that you might want to check out (ink! smart contracts, query storage, batch transaction, …) or sending XCM message.
  • We’ll be adding more working dapps to showcase more dedot features like interact with ink! smart contracts or send XCM in the future. Stay tuned!

Thank you all very much!