Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add StarknetLightClientPlugin #146

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

JunichiSugiura
Copy link
Member

@JunichiSugiura JunichiSugiura commented Feb 1, 2023

#145

Only Dust Tel Aviv Hacker Building Report

WTF is dip

Dip is a composable cross-platform application framework in Rust. It allows you build desktop apps, command line tools, games, and [WIP] web, mobile apps under the same scalable Entity Component System architecture. Unique point is that you can share logic between different platforms as a form of plugin. Transforming dip based desktop/web application into a 2D/3D game is as simple as swapping UI plugins targeting different platform. Your core logic stay the same no matter what platform you're targeting. Dip is based on a game engine called Bevy.

Scope of this PR

Provide StarknetLightClientPlugin that wraps Beerus and provide event driven interface for dip/bevy based developers. This is the first web3 plugin that dip offers besides Ledger device integration.

Demo

Very primitive demo of StarknetLightClientPlugin for Bevy game engine. It has desktop window made with React-like declarative UI (dip DesktopPlugin) with a button to fetch block number via Beerus.

I didn't have time to PoC yet but this plugin should also work in other platforms such as Bevy's 3D render plugins, dip CLIPlugin, etc.

  • UI window pops up around 1.20 mins. Please be patient while Beerus is synchronising :)
starknet-light-client-plugin-demo-compressed.mp4

[TODO] Architecture

sequenceDiagram
    participant UI component (VirtualDOM)
    participant Bevy ECS
    participant Light client (Beerus)
Loading

Things to improve in the future

Check my review comments for more details

  • Synchronisation of Beerus takes some time (around 1.20 mins). UI window should be rendered before staring a synchronisation and show some progress.
  • Right now, the RPC request can be trigger from UI but the result is only show in the console. There should be a global state that UI component can be listening to via custom hook, so it can re-render when the state changes.
// Super basic React-like UI component with a button to request block number via Beerus.

#[allow(non_snake_case)]
fn Root(cx: Scope) -> Element {
    let block_number = use_read(&cx, BLOCK_NUMBER); // <- Reading global state via custom hook

    let window = use_window::<UiAction, NoAsyncAction>(&cx); // <- to delegate action to ECS thread

   // rsx macro is the new jsx
    cx.render(rsx! {
        h1 { "Starknet Light Client (Beerus) Plugin Example" }
        
        p { "block_number: {block_number.value}" }

        button {
            onclick: move |_| window.send(UiAction::get_block_number()),
            "Get Block Number",
        }
    })
}

What's next

On this plugin (StraknetLightClientPlugin)

  • Support all JSON-RPC methods provided by Beerus.
  • Improve application startup time
  • Provide visual feedback on synchronisation progress
  • Expose Beerus response as a global state so UI component automatically re-renders when the state changes.

My initial intention for this experiment is to be used by Dojo project as a gaming client layer. As described in the previous section, the light client is still in a breeding edge. In the long-run, be able to verify on-chain data via Beerus light client provides great values because we don't have to trust untrusted data coming from full-node provider such as Alchemy or Infura. But for a sake of making playable games, we need more practical solution at least for now.

Apibara plugin

That being said, the next step for dip is to create another plugin that wraps Apibara Rust SDK which Dojo WG is already started working on. It requires game client to trust a server that Apibara is hosted but that would provide more realistic UX.

StarknetRsPlugin

Plugin to directly send JSON-RPC request to full-node without verification. You need to trust full-node provider but it's simpler than going through light client.

Auto Dojo <-> Bevy ECS synchronisation

The plugin should automatically sync on-chain ECS state with ECS on the client side (Bevy). As a gaming/application developer standpoint, they just query Entity/Component in Bevy instead of manually implementing logics to fetch data from the chain and store.

@vercel
Copy link

vercel bot commented Feb 1, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated
dip ✅ Ready (Inspect) Visit Preview 💬 Add your feedback Feb 4, 2023 at 7:48AM (UTC)

@JunichiSugiura JunichiSugiura changed the title Initialize Beerus light client from StarknetLightClientPlugin Add StarknetLightClientPlugin Feb 1, 2023
@JunichiSugiura
Copy link
Member Author

JunichiSugiura commented Feb 1, 2023

Instant crash after starting beerus client. Things are going great.

Screenshot 2023-02-01 at 11 38 36

@JunichiSugiura
Copy link
Member Author

JunichiSugiura commented Feb 2, 2023

@JunichiSugiura
Copy link
Member Author

This PR seems to fix the issue above.

eigerco/beerus#194

@JunichiSugiura
Copy link
Member Author

JunichiSugiura commented Feb 3, 2023

BeerusLightClient has to be clonable in order to fit into Bevy. I need to work on their repo first (potentially helios too)

Workaround for now is to spawn thread and listening to rpc request events via mpsc channel.
Get Res<Sender<RpcRequest>> from any system and emit rpc event.

@JunichiSugiura
Copy link
Member Author

JunichiSugiura commented Feb 4, 2023

starknet-light-client-plugin-demo-compressed.mp4

Improvement needed:

  • Takes time to sync full nodes on initialisation. Right now, synchronisation calls before desktop window starts, so not a good UX.
  • When click get_block_number button on UI, not it only logs result in console. need to think a way to update resources so that UI can listened to changes via custom hook.

Something like

// Super basic React-lie UI component
#[allow(non_snake_case)]
fn Root(cx: Scope) -> Element {
    let block_number = use_read(&cx, BLOCK_NUMBER);

    let window = use_window::<UiAction, NoAsyncAction>(&cx);

    cx.render(rsx! {
        h1 { "Starknet Light Client (Beerus) Plugin Example" }
        p { "block_number: {block_number.value}" }
        button {
            onclick: move |_| window.send(UiAction::get_block_number()),
            "Get Block Number",
        }
    })
}


#[derive(Debug)]
pub enum RpcRequest {
GetBlockNumber,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: support all JSON-RPC requests

Copy link
Member Author

@JunichiSugiura JunichiSugiura left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some improvements/concerns for the future iterations.

while let Some(msg) = rx.recv().await {
let block_tx_count = client.starknet_lightclient.block_number().await.unwrap();

println!("{block_tx_count}");
Copy link
Member Author

@JunichiSugiura JunichiSugiura Feb 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO:

  • support other methods with match
  • Update UiState with the request result so that UI component re-renders

});

let runner = StarketLightClientRunner::new();
let tx = runner.start(client);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: This takes some time. Should be triggered from startup_system so that it doesn't block UI window to spawn.

eyre = "0.6"
# beerus_core = { git = "https://github.com/keep-starknet-strange/beerus" }
# beerus_core = { path = "../../../../../JunichiSugiura/beerus/beerus_core" }
beerus_core = { git = "https://github.com/danilowhk/beerus", branch = "helios_0.2.0_implementation" }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Change to main branch once it's merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant