-
Notifications
You must be signed in to change notification settings - Fork 254
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
Yew Subxt WASM examples #968
Changes from 4 commits
cb618ab
2e57cbd
25931e0
b75b43e
0effd2d
b1d6581
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ | |
**/*.rs.bk | ||
**/.DS_Store | ||
cargo-timing* | ||
/examples/wasm-example/dist | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
name = "wasm-example" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
futures = "0.3.28" | ||
subxt = { path = "../../subxt", default-features = false, features = ["jsonrpsee-web"], target_arch = "wasm32" } | ||
yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DQ: does |
||
web-sys = "0.3.63" | ||
hex = "0.4.3" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<link data-trunk rel="scss" href="index.scss" /> | ||
<title>Yew App</title> | ||
</head> | ||
</html> |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,57 @@ | ||||||||
$primary: #24cc85; | ||||||||
$secondary: #1f624a; | ||||||||
$dark: #242a35; | ||||||||
|
||||||||
*{ | ||||||||
font-family: monospace; | ||||||||
color: $dark; | ||||||||
|
||||||||
} | ||||||||
|
||||||||
html{ | ||||||||
background-color: $dark; | ||||||||
display: flex; | ||||||||
justify-content: center; | ||||||||
height: 100%; | ||||||||
} | ||||||||
|
||||||||
h1{ | ||||||||
font-weight: bolder; | ||||||||
color: $dark; | ||||||||
} | ||||||||
|
||||||||
body{ | ||||||||
width: 800px; | ||||||||
max-width: 100%; | ||||||||
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; | ||||||||
height: 100%; | ||||||||
margin: 0px; | ||||||||
padding: 16px; | ||||||||
background-color: $primary; | ||||||||
} | ||||||||
|
||||||||
|
||||||||
p{ | ||||||||
white-space: pre-wrap; | ||||||||
border-radius: 8px; | ||||||||
padding: 8px; | ||||||||
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; | ||||||||
background-color: $dark; | ||||||||
color: white; | ||||||||
} | ||||||||
button{ | ||||||||
font-size: large; | ||||||||
padding: 8px 16px; | ||||||||
font-weight: bold; | ||||||||
background-color: $dark; | ||||||||
border: none; | ||||||||
border-radius: 8px; | ||||||||
color: white; | ||||||||
cursor: pointer; | ||||||||
display: block; | ||||||||
margin-top: 8px; | ||||||||
} | ||||||||
|
||||||||
button:hover{ | ||||||||
background-color: $secondary; | ||||||||
} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
//! This is a small WASM app using the Yew UI framework showcasing how to use Subxt's features in a WASM environment. | ||
//! | ||
//! To run the app locally use Trunk, a WASM bundler: | ||
//! ``` | ||
//! cargo install --locked trunk | ||
//! ``` | ||
//! Run the app locally: | ||
//! ``` | ||
//! trunk serve --open | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After running this command on the repo |
||
//! ``` | ||
//! You need to have a local polkadot/substrate node with it's JSON-RPC HTTP server running at 127.0.0.1:9933 in order for the examples to be working. | ||
//! Also make sure your browser supports WASM. | ||
use futures::{self, FutureExt}; | ||
|
||
use yew::prelude::*; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: do we need to import everything here? |
||
mod services; | ||
|
||
fn main() { | ||
yew::Renderer::<SubxtExamplesComponent>::new().render(); | ||
} | ||
|
||
struct SubxtExamplesComponent { | ||
operation_title: Option<AttrValue>, | ||
lines: Vec<AttrValue>, | ||
} | ||
|
||
enum Message { | ||
Error(subxt::Error), | ||
Reload, | ||
Line(AttrValue), | ||
Lines(Vec<AttrValue>), | ||
ButtonClick(Button), | ||
} | ||
|
||
enum Button { | ||
SubscribeFinalized, | ||
FetchConstant, | ||
FetchEvents, | ||
} | ||
|
||
impl Component for SubxtExamplesComponent { | ||
type Message = Message; | ||
type Properties = (); | ||
|
||
fn create(_ctx: &Context<Self>) -> Self { | ||
SubxtExamplesComponent { | ||
lines: Vec::new(), | ||
operation_title: None, | ||
} | ||
} | ||
|
||
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool { | ||
match msg { | ||
Message::Error(err) => { | ||
self.lines.push(err.to_string().into()); | ||
} | ||
Message::Reload => { | ||
let window = web_sys::window().expect("Failed to access the window object"); | ||
window | ||
.location() | ||
.reload() | ||
.expect("Failed to reload the page"); | ||
} | ||
Message::Line(line) => { | ||
self.lines.push(line); | ||
} | ||
Message::Lines(mut lines) => { | ||
self.lines.append(&mut lines); | ||
} | ||
Message::ButtonClick(button) => match button { | ||
Button::SubscribeFinalized => { | ||
self.operation_title = Some("Subscribe to finalized blocks:".into()); | ||
let cb: Callback<AttrValue> = ctx.link().callback(Message::Line); | ||
ctx.link() | ||
.send_future(services::subscribe_to_finalized_blocks(cb).map(|result| { | ||
let err = result.unwrap_err(); | ||
Message::Error(err) | ||
})); | ||
} | ||
Button::FetchConstant => { | ||
self.operation_title = | ||
Some("Fetch the constant \"block_length\" of \"System\" pallet:".into()); | ||
ctx.link() | ||
.send_future(services::fetch_constant_block_length().map(|result| { | ||
match result { | ||
Ok(value) => Message::Line( | ||
format!( | ||
"constant \"block_length\" of \"System\" pallet:\n {value}" | ||
) | ||
.into(), | ||
), | ||
Err(err) => Message::Error(err), | ||
} | ||
})) | ||
} | ||
Button::FetchEvents => { | ||
self.operation_title = Some("Fetch events:".into()); | ||
ctx.link() | ||
.send_future(services::fetch_events_dynamically().map( | ||
|result| match result { | ||
Ok(value) => { | ||
Message::Lines(value.into_iter().map(AttrValue::from).collect()) | ||
} | ||
Err(err) => Message::Error(err), | ||
}, | ||
)) | ||
} | ||
}, | ||
} | ||
true | ||
} | ||
|
||
fn view(&self, ctx: &Context<Self>) -> Html { | ||
let reload: Callback<MouseEvent> = ctx.link().callback(|_| Message::Reload); | ||
|
||
let subscribe_finalized = ctx | ||
.link() | ||
.callback(|_| Message::ButtonClick(Button::SubscribeFinalized)); | ||
|
||
let fetch_constant = ctx | ||
.link() | ||
.callback(|_| Message::ButtonClick(Button::FetchConstant)); | ||
|
||
let fetch_events = ctx | ||
.link() | ||
.callback(|_| Message::ButtonClick(Button::FetchEvents)); | ||
|
||
html! { | ||
<div> | ||
if let Some(operation_title) = &self.operation_title{ | ||
<button onclick={reload}>{"🡄 Back"}</button> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: the prefixed characters do not render properly on my machine, could we change it to something else? |
||
<h1>{operation_title}</h1> | ||
if self.lines.is_empty(){ | ||
<p>{"Loading..."}</p> | ||
} | ||
else{ | ||
|
||
} | ||
{ for self.lines.iter().map(|line| html! {<p> {line} </p>}) } | ||
} | ||
else{ | ||
<> | ||
<h1>{"Subxt Examples"}</h1> | ||
<button onclick={subscribe_finalized}>{"Example: Subscribe to Finalized blocks"}</button> | ||
<button onclick={fetch_constant}>{"Example: Fetch constant value"}</button> | ||
<button onclick={fetch_events}>{"Example: Fetch events"}</button> | ||
</> | ||
} | ||
</div> | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: