--- :: master: title1
--- :: master: title1
--- :: master: title1
- Good tooling is the critical component to turbocharge your velocity
- Build a native app that users / team members can install
- No unholy mash-up of NPM packages, localhost servers, and broken dependencies
- Doesn't break every second week. Binaries just keep working
- Use all the native Solana libraries directly from Rust.
- Dioxus is Native apps on a Turbo
- One codebase can support many targets
- Desktop app: macOS, Linux, Windows
- Web App
- Fullstack Server app
- LiveView apps
- TUI (Terminal App)
- Mobile app (in the future)
- Hot Reload to iterate quickly
image ists not me its y0uo
- Things change
- Documentation becomes outdated
- If there even is documentation
- Rust makes an already difficult platform even more difficult
explorer
inspector
ebou
fn app(cx: Scope) -> Element {
let mut count = use_state(&cx, || 0);
render! {
h1 { "Count: {count}" }
button { onclick: move |_| count += 1, "+" }
button { onclick: move |_| count -= 1, "-" }
}
}
image of counter example
fn app(cx: Scope) -> Element {
let mut count = use_state(&cx, || 0);
render! {
}
}
#[inline_props]
fn Button<'a>(cx: Scope<'a>, title: &'a str, onclick: EventHandler<'a, ()>) -> Element<'a> {
render! {
button {
class: "button-style",
onclick: move |_| onclick.call(()),
"{title}"
}
}
}
schema1
schema2
- Electron brings its own Blink Web WebView
- Chrome is slower than WebView
- Electron is slow because Javascript is slow
- Dioxus uses native Rust
- The WebView doesn't process. Just a renderer.
- Millions of dollars have been spend on making HTML & CSS Phast
- Rust consumes far less memory than Javascript
- Actually, WebView Buttons, Checkboxes are all native by default
- Text Rendering is native by default
- Video Rendering: Native.
- Accessibility: Native
- And, you can always hook up a different renderer
platforms image
tui image
blitz image
screenshot of app
Free NFT from the collection for the first good question after the talk
crates io solana + nft
pub fn get_balance(pubkey: &Pubkey) -> Result<SolanaBalance, SolanaError> {
let rpc = RpcClient::new("https://api.mainnet-beta.solana.com");
let acc = rpc.get_account(&pubkey)?;
Ok(SolanaBalance {
lamports: acc.lamports,
sol: (acc.lamports as f64) / 1000000000.0,
})
}
let token_program = Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")?;
let rpc = RpcClient::new("https://api.mainnet-beta.solana.com".into());
let pubkey = Pubkey::from_str("Eggs2iFRUm3RirAJuWeAdBRyk6br9q8TqFkGbPv11px4")?;
let commitment = CommitmentConfig::finalized();
let accounts = rpc
.get_token_accounts_by_owner_with_commitment(
&pubkey,
TokenAccountsFilter::ProgramId(token_program),
commitment,
)?
.value;
Some more complexity (thanks Solana). Example in the Repository.
pub struct Nft {
pub name: String,
pub symbol: String,
pub description: String,
pub image: String,
}
pub fn app(cx: Scope) -> Element {
let data = use_future(cx, (), |_| async move {
get_nfts(
"Eggs2iFRUm3RirAJuWeAdBRyk6br9q8TqFkGbPv11px4",
Cluster::MainnetBeta,
)
.await
});
let data = ...;
match data.value() {
Some(Ok(nfts)) => render! {
List {
nfts: nfts.clone()
}
},
Some(Err(e)) => render! {
div { "Error: {e:?}" }
},
None => render! {
render! {
div { class: "loader" }
}
},
}
#[inline_props]
fn List(cx: Scope, nfts: Vec<Nft>) -> Element {
render! {
div {
class: "nft-list",
for item in nfts.iter() {
h3 {
"{item.name}"
}
}
}
}
}
fn main() {
let style = include_str!("../style.css");
let config = Config::new()
.with_window(default_window())
.with_custom_head(
format!(
r#"
<title>Hello Solana</title>
<style>{style}</style>
"#
)
.into(),
);
dioxus_desktop::launch_cfg(solana_example::app, config);
}
#[inline_props]
fn Nft(cx: Scope, item: Nft) -> Element {
render! {
div {
key: "{item.name}",
class: "nft",
img {
src: "{item.image}",
}
div {
class: "label-secondary",
"{item.name}"
}
}
}
}
#[inline_props]
fn List(cx: Scope, nfts: Vec<Nft>) -> Element {
render! {
div {
class: "nft-list",
for item in nfts.iter() {
Nft {
item: item.clone()
}
}
}
}
}
fn popup(cx: Scope) -> Element {
cx.render(rsx! {
img {
src: "...",
}
})
}
let window = dioxus_desktop::use_window(cx);
let dom = VirtualDom::new(popup);
window.new_window(dom, Default::default());
Take any of the three apps (app1, app2, app3) and try to improve upon it
- app1: Basics
- app2: Display proper Nft
- app3: Open new Window, Search for addresses
- Click a Nft to show more info (description, attributes)
- Open Mint in a new browser
- Show Nfts in a Sidebar
- Figure out how to show Nfts and other tokens
- Show the amount of Nfts that user owns
- Just to something completely different with Dioxus