From 382138c699966cc3f54d4d72da9d011a6958db8d Mon Sep 17 00:00:00 2001 From: Louis Pahlavi Date: Wed, 29 Jan 2025 11:53:53 +0100 Subject: [PATCH 1/3] build: Add 'js' Cargo feature flag for WASM builds Previously, the wasm32 target implicitly assumed a browser environment, which caused issues when building for non-browser WASM environments due to the unconditional inclusion of `wasm-bindgen`. This commit introduces an explicit 'js' feature flag, making `wasm-bindgen` and `js-sys` conditional dependencies. This allows greater flexibility for different WASM execution environments. Related to #47 --- interface/Cargo.toml | 5 +++-- interface/src/lib.rs | 2 +- interface/src/wasm.rs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/Cargo.toml b/interface/Cargo.toml index d4680dd..9478ddc 100644 --- a/interface/Cargo.toml +++ b/interface/Cargo.toml @@ -28,8 +28,8 @@ solana-program-error = { workspace = true } solana-pubkey = { workspace = true, default-features = false } [target.'cfg(target_arch = "wasm32")'.dependencies] -js-sys = "0.3.72" -wasm-bindgen = "0.2" +js-sys = { version = "0.3.72", optional = true } +wasm-bindgen = { version = "0.2", optional = true } [dev-dependencies] anyhow = "1.0.89" @@ -56,6 +56,7 @@ frozen-abi = [ "solana-pubkey/frozen-abi", "solana-pubkey/std" ] +js = ["dep:js-sys", "dep:wasm-bindgen"] serde = ["dep:serde", "dep:serde_derive", "solana-pubkey/serde"] [lib] diff --git a/interface/src/lib.rs b/interface/src/lib.rs index efeaf39..2336abe 100644 --- a/interface/src/lib.rs +++ b/interface/src/lib.rs @@ -5,7 +5,7 @@ pub mod error; pub mod instruction; -#[cfg(target_arch = "wasm32")] +#[cfg(feature = "js")] mod wasm; #[cfg(test)] diff --git a/interface/src/wasm.rs b/interface/src/wasm.rs index 8068bf2..c96f21d 100644 --- a/interface/src/wasm.rs +++ b/interface/src/wasm.rs @@ -1,5 +1,5 @@ //! `SystemInstruction` Javascript interface -#![cfg(target_arch = "wasm32")] +#![cfg(feature = "js")] #![allow(non_snake_case)] use { crate::instruction::{ From ea6716a603181a46c0486362f2b5b50cc65f715d Mon Sep 17 00:00:00 2001 From: Louis Pahlavi Date: Wed, 14 May 2025 13:51:00 +0200 Subject: [PATCH 2/3] Create solana-system-interface-wasm-js crate --- Cargo.lock | 33 +++++++++++++++++-- Cargo.toml | 1 + interface-wasm-js/Cargo.toml | 26 +++++++++++++++ interface-wasm-js/README.md | 12 +++++++ .../wasm.rs => interface-wasm-js/src/lib.rs | 0 interface/Cargo.toml | 7 +--- interface/src/lib.rs | 2 -- 7 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 interface-wasm-js/Cargo.toml create mode 100644 interface-wasm-js/README.md rename interface/src/wasm.rs => interface-wasm-js/src/lib.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index b31c208..fd48da6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5050,7 +5050,6 @@ version = "1.0.0" dependencies = [ "anyhow", "borsh 1.5.5", - "js-sys", "num-traits", "serde", "serde_derive", @@ -5072,7 +5071,6 @@ dependencies = [ "static_assertions", "strum", "strum_macros", - "wasm-bindgen", ] [[package]] @@ -5091,6 +5089,37 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "solana-system-interface-wasm-js" +version = "1.0.0" +dependencies = [ + "anyhow", + "borsh 1.5.5", + "js-sys", + "num-traits", + "serde", + "serde_derive", + "solana-account-info", + "solana-cpi", + "solana-decode-error", + "solana-example-mocks", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-instruction", + "solana-logger", + "solana-msg", + "solana-nonce", + "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-system-interface 1.0.0", + "static_assertions", + "strum", + "strum_macros", + "wasm-bindgen", +] + [[package]] name = "solana-system-program" version = "2.2.1" diff --git a/Cargo.toml b/Cargo.toml index 1e1655a..02ade8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "clients/rust", "interface", + "interface-wasm-js", "program", ] diff --git a/interface-wasm-js/Cargo.toml b/interface-wasm-js/Cargo.toml new file mode 100644 index 0000000..67c5223 --- /dev/null +++ b/interface-wasm-js/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "solana-system-interface-wasm-js" +version = "1.0.0" +description = "Instructions and constructors for the System program" +readme = "README.md" +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] + +[dependencies] +solana-instruction = { workspace = true, features = ["bincode", "std"], optional = true } +solana-pubkey = { workspace = true, default-features = false } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +js-sys = { version = "0.3.72", optional = true } +wasm-bindgen = { version = "0.2", optional = true } + +[lib] +crate-type = ["cdylib"] diff --git a/interface-wasm-js/README.md b/interface-wasm-js/README.md new file mode 100644 index 0000000..edc0b72 --- /dev/null +++ b/interface-wasm-js/README.md @@ -0,0 +1,12 @@ +

+ + Solana + +

+ +# Solana System Interface WASM JS + +Use the Solana System Interface WASM JS crate to build a JS package with `wasm-pack` usable in Node or browser environments. +See the [Solana System Interface Crate](https://crates.io/crates/solana-system-interface) instead for on-chain programs and client-side applications. + +Still have questions? Ask us on [Stack Exchange](https://sola.na/sse) \ No newline at end of file diff --git a/interface/src/wasm.rs b/interface-wasm-js/src/lib.rs similarity index 100% rename from interface/src/wasm.rs rename to interface-wasm-js/src/lib.rs diff --git a/interface/Cargo.toml b/interface/Cargo.toml index 9478ddc..e195de4 100644 --- a/interface/Cargo.toml +++ b/interface/Cargo.toml @@ -27,10 +27,6 @@ solana-msg = { workspace = true } solana-program-error = { workspace = true } solana-pubkey = { workspace = true, default-features = false } -[target.'cfg(target_arch = "wasm32")'.dependencies] -js-sys = { version = "0.3.72", optional = true } -wasm-bindgen = { version = "0.2", optional = true } - [dev-dependencies] anyhow = "1.0.89" borsh = { version = "1.5.1", features = ["derive", "unstable__schema"] } @@ -56,8 +52,7 @@ frozen-abi = [ "solana-pubkey/frozen-abi", "solana-pubkey/std" ] -js = ["dep:js-sys", "dep:wasm-bindgen"] serde = ["dep:serde", "dep:serde_derive", "solana-pubkey/serde"] [lib] -crate-type = ["cdylib", "rlib"] +crate-type = ["rlib"] diff --git a/interface/src/lib.rs b/interface/src/lib.rs index 2336abe..e0514cd 100644 --- a/interface/src/lib.rs +++ b/interface/src/lib.rs @@ -5,8 +5,6 @@ pub mod error; pub mod instruction; -#[cfg(feature = "js")] -mod wasm; #[cfg(test)] static_assertions::const_assert!(MAX_PERMITTED_DATA_LENGTH <= u32::MAX as u64); From 7443ba4f583d004d4d0245706f55e51fa66000b0 Mon Sep 17 00:00:00 2001 From: Louis Pahlavi Date: Wed, 14 May 2025 14:23:58 +0200 Subject: [PATCH 3/3] Export static methods outside impl block --- Cargo.lock | 20 ---- Cargo.toml | 1 + interface-wasm-js/Cargo.toml | 7 +- interface-wasm-js/src/lib.rs | 197 ++++++++++++++++++----------------- 4 files changed, 105 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ee480e..7e3ada5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4803,30 +4803,10 @@ dependencies = [ name = "solana-system-interface-wasm-js" version = "1.0.0" dependencies = [ - "anyhow", - "borsh 1.5.5", "js-sys", - "num-traits", - "serde", - "serde_derive", - "solana-account-info", - "solana-cpi", - "solana-decode-error", - "solana-example-mocks", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-instruction", - "solana-logger", - "solana-msg", - "solana-nonce", - "solana-program", - "solana-program-entrypoint", - "solana-program-error", "solana-pubkey", "solana-system-interface 1.0.0", - "static_assertions", - "strum", - "strum_macros", "wasm-bindgen", ] diff --git a/Cargo.toml b/Cargo.toml index a82ecfd..945f395 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,4 @@ solana-program = { version = "2.2.1", default-features = false } solana-program-entrypoint = "2.2.1" solana-program-error = "2.2.1" solana-pubkey = { version = "2.2.1", default-features = false } +solana-system-interface = { path = "interface" } diff --git a/interface-wasm-js/Cargo.toml b/interface-wasm-js/Cargo.toml index 67c5223..96d3bae 100644 --- a/interface-wasm-js/Cargo.toml +++ b/interface-wasm-js/Cargo.toml @@ -15,12 +15,13 @@ all-features = true rustdoc-args = ["--cfg=docsrs"] [dependencies] -solana-instruction = { workspace = true, features = ["bincode", "std"], optional = true } +solana-instruction = { workspace = true, features = ["bincode", "std"] } solana-pubkey = { workspace = true, default-features = false } +solana-system-interface = { workspace = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -js-sys = { version = "0.3.72", optional = true } -wasm-bindgen = { version = "0.2", optional = true } +js-sys = { version = "0.3.72" } +wasm-bindgen = { version = "0.2" } [lib] crate-type = ["cdylib"] diff --git a/interface-wasm-js/src/lib.rs b/interface-wasm-js/src/lib.rs index c96f21d..78e78f0 100644 --- a/interface-wasm-js/src/lib.rs +++ b/interface-wasm-js/src/lib.rs @@ -1,118 +1,121 @@ //! `SystemInstruction` Javascript interface -#![cfg(feature = "js")] #![allow(non_snake_case)] use { - crate::instruction::{ - advance_nonce_account, allocate, allocate_with_seed, assign, assign_with_seed, - authorize_nonce_account, create_account, create_account_with_seed, create_nonce_account, - transfer, transfer_with_seed, withdraw_nonce_account, SystemInstruction, - }, solana_instruction::Instruction, solana_pubkey::Pubkey, + solana_system_interface::instruction::{ + advance_nonce_account, allocate_with_seed, assign_with_seed, authorize_nonce_account, + create_account, create_account_with_seed, create_nonce_account, transfer_with_seed, + withdraw_nonce_account, + }, wasm_bindgen::prelude::*, }; #[wasm_bindgen] -impl SystemInstruction { - pub fn createAccount( - from_pubkey: &Pubkey, - to_pubkey: &Pubkey, - lamports: u64, - space: u64, - owner: &Pubkey, - ) -> Instruction { - create_account(from_pubkey, to_pubkey, lamports, space, owner) - } +pub fn createAccount( + from_pubkey: &Pubkey, + to_pubkey: &Pubkey, + lamports: u64, + space: u64, + owner: &Pubkey, +) -> Instruction { + create_account(from_pubkey, to_pubkey, lamports, space, owner) +} - pub fn createAccountWithSeed( - from_pubkey: &Pubkey, - to_pubkey: &Pubkey, - base: &Pubkey, - seed: &str, - lamports: u64, - space: u64, - owner: &Pubkey, - ) -> Instruction { - create_account_with_seed(from_pubkey, to_pubkey, base, seed, lamports, space, owner) - } +#[wasm_bindgen] +pub fn createAccountWithSeed( + from_pubkey: &Pubkey, + to_pubkey: &Pubkey, + base: &Pubkey, + seed: &str, + lamports: u64, + space: u64, + owner: &Pubkey, +) -> Instruction { + create_account_with_seed(from_pubkey, to_pubkey, base, seed, lamports, space, owner) +} - pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction { - assign(pubkey, owner) - } +#[wasm_bindgen] +pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction { + solana_system_interface::instruction::assign(pubkey, owner) +} - pub fn assignWithSeed( - pubkey: &Pubkey, - base: &Pubkey, - seed: &str, - owner: &Pubkey, - ) -> Instruction { - assign_with_seed(pubkey, base, seed, owner) - } +#[wasm_bindgen] +pub fn assignWithSeed(pubkey: &Pubkey, base: &Pubkey, seed: &str, owner: &Pubkey) -> Instruction { + assign_with_seed(pubkey, base, seed, owner) +} - pub fn transfer(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction { - transfer(from_pubkey, to_pubkey, lamports) - } +#[wasm_bindgen] +pub fn transfer(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction { + solana_system_interface::instruction::transfer(from_pubkey, to_pubkey, lamports) +} - pub fn transferWithSeed( - from_pubkey: &Pubkey, - from_base: &Pubkey, - from_seed: String, - from_owner: &Pubkey, - to_pubkey: &Pubkey, - lamports: u64, - ) -> Instruction { - transfer_with_seed( - from_pubkey, - from_base, - from_seed, - from_owner, - to_pubkey, - lamports, - ) - } +#[wasm_bindgen] +pub fn transferWithSeed( + from_pubkey: &Pubkey, + from_base: &Pubkey, + from_seed: String, + from_owner: &Pubkey, + to_pubkey: &Pubkey, + lamports: u64, +) -> Instruction { + transfer_with_seed( + from_pubkey, + from_base, + from_seed, + from_owner, + to_pubkey, + lamports, + ) +} - pub fn allocate(pubkey: &Pubkey, space: u64) -> Instruction { - allocate(pubkey, space) - } +#[wasm_bindgen] +pub fn allocate(pubkey: &Pubkey, space: u64) -> Instruction { + solana_system_interface::instruction::allocate(pubkey, space) +} - pub fn allocateWithSeed( - address: &Pubkey, - base: &Pubkey, - seed: &str, - space: u64, - owner: &Pubkey, - ) -> Instruction { - allocate_with_seed(address, base, seed, space, owner) - } +#[wasm_bindgen] +pub fn allocateWithSeed( + address: &Pubkey, + base: &Pubkey, + seed: &str, + space: u64, + owner: &Pubkey, +) -> Instruction { + allocate_with_seed(address, base, seed, space, owner) +} - pub fn createNonceAccount( - from_pubkey: &Pubkey, - nonce_pubkey: &Pubkey, - authority: &Pubkey, - lamports: u64, - ) -> js_sys::Array { - let instructions = create_nonce_account(from_pubkey, nonce_pubkey, authority, lamports); - instructions.into_iter().map(JsValue::from).collect() - } +#[wasm_bindgen] +pub fn createNonceAccount( + from_pubkey: &Pubkey, + nonce_pubkey: &Pubkey, + authority: &Pubkey, + lamports: u64, +) -> js_sys::Array { + let instructions = create_nonce_account(from_pubkey, nonce_pubkey, authority, lamports); + instructions.into_iter().map(JsValue::from).collect() +} - pub fn advanceNonceAccount(nonce_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction { - advance_nonce_account(nonce_pubkey, authorized_pubkey) - } +#[wasm_bindgen] +pub fn advanceNonceAccount(nonce_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction { + advance_nonce_account(nonce_pubkey, authorized_pubkey) +} - pub fn withdrawNonceAccount( - nonce_pubkey: &Pubkey, - authorized_pubkey: &Pubkey, - to_pubkey: &Pubkey, - lamports: u64, - ) -> Instruction { - withdraw_nonce_account(nonce_pubkey, authorized_pubkey, to_pubkey, lamports) - } +#[wasm_bindgen] +pub fn withdrawNonceAccount( + nonce_pubkey: &Pubkey, + authorized_pubkey: &Pubkey, + to_pubkey: &Pubkey, + lamports: u64, +) -> Instruction { + withdraw_nonce_account(nonce_pubkey, authorized_pubkey, to_pubkey, lamports) +} - pub fn authorizeNonceAccount( - nonce_pubkey: &Pubkey, - authorized_pubkey: &Pubkey, - new_authority: &Pubkey, - ) -> Instruction { - authorize_nonce_account(nonce_pubkey, authorized_pubkey, new_authority) - } +#[wasm_bindgen] +pub fn authorizeNonceAccount( + nonce_pubkey: &Pubkey, + authorized_pubkey: &Pubkey, + new_authority: &Pubkey, +) -> Instruction { + authorize_nonce_account(nonce_pubkey, authorized_pubkey, new_authority) }