In "Jutus", "J" is from "Javascipt" and "utus" is from "Plutus". With "Javascript" we mean both Javascript and Typescript.
As a Plutus contract developer, I want to write my Smart Contracts in Javascript.
The world has 25 million developers, and half of them use Javascript. The web is the global platform. So, let's write Plutus by writing in Javascript !
We use both established and emerging open source components and glue them together in a most (cost-)effective way in order to produce an end-to-end compilation pipeline. Our strategy is as follows:
- We use
swc
to parse Javascript into their Abstract Syntax Tree (AST). - We transform the
swc
AST to our own Intermediate Representation (IR). - We compile our IR to
aiken
AST(s). - We use
aiken
to type-check and compile to their Untyped Plutus Core (UPLC) representation. From here it should be straightforward (viaaiken
again) to generate the binary representation of UPLC.
You may want to check the section on architecture for a visualization of the above.
This is a feasibility study and a proof-of-concept, and, as such, not ready for production. But the results are positive, in the sense we prove that the original idea is doable. We can also take the whole work a step further by using our IR as a compilation target for other languages. For instance, one could write Plutus smart contracts in Python.
We chose Rust as the implementation language because everything we needed was already there in Rust. This is a very pragmatic and modern language with a huge ecosystem.
Please check the examples folder if you want to follow the logic of how
everything fits together. The whole compilation pipeline can also be
seen encoded as pub fn end_to_end
in js_compiler.rs
.
Here is the general compilation pipeline architecture. Dotted lines denote something enabled by this project but not implemented yet.
flowchart LR
subgraph "Front-end"
A
AA
AAA
end
subgraph "Front-end AST"
B
BBB
end
A([Typescript]) --> B([swc AST])
AA([Javascript]) --> B
B --> C([jutus IR])
AAA(Language X) -..-> BBB("X" AST)
BBB -..-> C
C --> D([aiken untyped AST])
D --> E([aiken typed AST])
E --> F([aiken UPLC AST])
F -..-> G([UPLC binary format])
subgraph "Back-end AST"
F
end