⚠️ This project has been archived. It is no longer maintained.
An ink! Playground which provides a Browser based IDE for editing Smart Contracts written in ink!. A live deployment of the App can be found under ink-playground.substrate.io.
Features:
- Uses the Monaco editor
- Implements a WebAssembly version of Rust Analyzer for code editing
- Allows saving and sharing of Smart Contract code
- Implements a one click compile functionality of ink! Smart Contracts to WASM which is provided by a backend service
- Getting started
- Detailed usage instructions:
- Overview of the (sub-)repos
- The Dockerfiles for ink! playground
Before proceeding you need to configure the following environment variables (either on your terminal or better persist them into your .zshrc
file):
export PATH="/usr/local/opt/llvm/bin/:$PATH"
export CC=/usr/local/opt/llvm/bin/clang
export AR=/usr/local/opt/llvm/bin/llvm-ar
The ink! playground is a fronted app which is developed using TypeScript and React. It is contained in the packages/playground
folder.
The repo contains a Rust backend which is implemented with the actix-web framework and which can be found in the 'crates/backend' folder.
The backend serves the frontend app and it also provides the backend services for compilation and Github gists creation(which we use to provide the code sharing functionality).
To clone and build the whole project on your local computer, enter:
-
git clone https://github.com/paritytech/ink-playground
-
cd ink-playground
-
make install
-
make generate
-
make build
Then pull and tag the docker images which are used by the backend to compile, test & format Smart Contracts:
make docker-pull-images
Finally, start the backend with:
make backend-run
The last command starts the Rust webserver locally on your computer. You can then access localhost:4000
from your browser to open the locally compiled ink! Playground open.
Important commands from the make file:
make install
Installs all the required TypeScript dependencies from all monorepo packages by usingyarn install
.make generate
There are parts of the Frontend which are generated by some rust crates. Namely, these are:- rust analyzer
The WebAssembly version of Rust Analyzer which is run by Frontend through some Web Workers. Generating only the rust analyzer WASM file can be done withmake generate-rust-analyzer
. - change.json
A serialized version of the CrateGraph and project source dependencies of an ink! Smart Contract. This file is provided to the WASM version of rust analyzer and is generated under/packages/_generated/change
. Generating only the change.json file can be done withmake generate change-json
. - bindings
The actix-web Webserver backend provides some endpoints to the Frontend (/compile
,/test
,/gist
). The crategenerate-bindings
from the Rust Monorepo automatically creates TypeScript types for the communication with these endpoints and provides them in/packages/_generated/commontypes
. Generating only the bindings can be done withmake generate bindings
.
- rust analyzer
make build
Builds the complete ink! Playground, involves:- frontend
the react Frontend which needs to be provided with all three ingredients which are generated by
make generate
, as well as all npm dependencies which are installed bymake install
. Can also be build independently bymake playground-build
. - backend
the actix-web backend which serves the Frontend and provides endpoint for testing, compilation and sharing of Smart Contract code. Can also be build independently by
make backend-build
.
- frontend
the react Frontend which needs to be provided with all three ingredients which are generated by
make backend-run
Starts a the actix web server backend and serves the release version of the playground frontend from the folderpackages/playground/dist
. Make sure to runmake build
first to build all the required Rust and frontend dependencies.make playground-start
Starts a dev build of the frontend repo of ink! Playground which allows for easy debugging of the Frontend code / UI, involving Rust Analyzer. Note that the compile/gist functionalities will not be available when invokingmake playground-start
make docker-build
Then deployment of the ink! Playground app is done in our CI by building and uploading the docker image which we generate from our Dockerfile. Running makedocker-build
generates this docker image and tags it withink-playground
.make docker-run
Starts the Docker container of playground under the sysbox runtime. Make sure that you have the sysbox docker runtime installed on your computer. Instructions on how to install it can be found here.make ci
Withmake ci
, we run the majority of tests which we execute in our Github CI.
We can divide this Repo into two main contributions:
- The folder
crates
is a monorepo containing the Rust source code, its separate crates serve functionalities like the web server which serves the frontend app, the backend services for Smart Contract compilation and Github Gist generation (code sharing) or the rust analyzer functionalities for the IDE. - The folder
packages
is a TypeScript/React monorepo, containing the Frontend App which is served by the Rust backend.
-
This is the main crate of the web server which serves the frontend app. It is based on the Actix Web framework. It serves the directory of the compiled playground app which is located in the
/packages/playground/dist
folder after executingmake build
(which involves the compilation of the production bundle of the Frontend app). -
The IDE of the frontend app contains a WebAssembly version of Rust Analyzer. We need to provide Rust Analyzer the source code and crate graph of the analyzed smart contract. Usually, Rust Analyzer will scan the file system, load the dependency data of a rust project into an object, the
change
object and will send this object to its db. Since we can not access the file system in browser based wasm, we had to find another approach. For this we (de-)serialize thechange
object which is encoding the data. This crate contains the methods/traits to (de-)serialize thechange
object. -
This is the sample crate which serves as a blueprint for creating the serialized
change
object. -
Parses Crates and CrateGraph (the package dependency graph) of a Rust Project into a JSON file for Rust Analyzer(=RA) and provides a library for (de-)serialization of these data structures which can be referenced by a WASM implementation of RA.
For a detailed description, refer to the corresponding section of ARCHITECTURE.md
Enter:
gh clone https://github.com/paritytech/ink-playground
cd ink-playground
cargo run -p crate-extractor -- create -i <input> -o <output>
Where
<input>
points to theCargo.toml
of the project you which to analyze and<output>
denotes the path to the resulting '.json' file. Both are optional parameters and default to/Cargo.toml
and./change.json
. -
Utilizes ts-rs to auto-generate TypeScript bindings for the API endpoints that the Actix Web framework of the
backend
crate provides. The bindings are generated into the/packages/_generated/commontypes
folder, where they are consumed by the Frontend App. -
A LSP (Language Server Protocol) of Rust Analyzer for the monaco editor which is compiled to WebAssembly and which we execute in the Browser. This crate gets compiled to the
/packages/playground/pkg
subfolder of theplayground
package. Its compiled version provides the executable WebAssembly code and the corresponding TypeScript types. -
Provides the sandbox environment which triggers the compilation of ink! Smart Contracts which is executed by the backend server from the
backend
crate.
This is the main Frontend Webapp which provides the ink! Playground with Rust Analyzer and compilation functionalities.
This isolates the components providing the monaco editor with integrated Rust Analyzer and the API endpoints for code compilation and Github gist creation into its own package.
Contains the basic UI building blocks. Makes use of PRIMEREACT UI library.
This is the target directory for auto generated types, files & bindings. It currently contains the change
package which receives the change.json
file from the crate_extractor
crate and the commontypes
package which carries the bindings and types which allow the Frontend (specifically the API being contained in ink-editor
package) to communicate with the backend service for code compilation and Gist generation.
Based on the jest testing framework, this packages executes some basic tests against an already running playground container (serves website, provides compile endpoint).
We have two Dockerfiles for two different docker images in this repo: ink-playground
and ink-compiler
:
-
ink-compiler
Is used to compile ink! Smart Contracts in a sandboxed environment. We execute the resulting image in a sandboxed environment without network access. The image is a derived fromdocker.io/paritytech/ink-ci-linux:production
and ships with a pre-compiled ink! Smart Contract. -
ink-playground
Is the main ink! Playground Dockerfile which is generated by the./Dockerfile
. It is used to deploy the playground on our server. It is executed by using Nestybox's Sysbox runtime. We require this runtime to compile ink! Smart Contracts through a sandboxed Docker in Docker execution within the executed Docker image by using theink-compiler
Docker image.The Image is build in multiple steps by a multi stage build process to improve its image size.
For a better understanding of the steps which are involved in building this image, refer to the build dependencies section of ARCHITECTURE.md.