Skip to content

Commit e47b045

Browse files
committed
chore: Added examples, WASM doc, format
Signed-off-by: gsstoykov <[email protected]>
1 parent b8ced44 commit e47b045

File tree

144 files changed

+906
-571
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

144 files changed

+906
-571
lines changed

WASM_SUPPORT.md

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
# WASM Support for Hedera Rust SDK
2+
3+
## Overview
4+
5+
The Hedera Rust SDK now supports **WebAssembly (WASM)** compilation for transaction building and serialization! This enables JavaScript applications to leverage Rust's type safety and performance for constructing Hedera transactions.
6+
7+
## ✅ What Works in WASM
8+
9+
### Transaction Building
10+
- ✅ All transaction types can be built (Transfer, FileCreate, TokenCreate, etc.)
11+
- ✅ Transaction IDs can be generated
12+
- ✅ Transaction parameters can be set (memo, fees, node IDs, etc.)
13+
-**Transactions can be frozen** (`freeze()`)
14+
-**Transactions can be signed** (`sign()`, `sign_with()`)
15+
- ✅ Transactions can be serialized to bytes (`to_bytes()`)
16+
- ✅ Transactions can be deserialized from bytes (`from_bytes()` via `AnyTransaction`)
17+
18+
### Core Types
19+
-`AccountId`, `FileId`, `TokenId`, `TopicId`, etc.
20+
-`Hbar` and amount types
21+
-`TransactionId` generation
22+
-`PrivateKey` and `PublicKey` (generation and signing)
23+
-`AnyTransaction` for type-erased transactions
24+
- ✅ All transaction data types
25+
26+
### Protobuf Serialization
27+
- ✅ Protobuf encoding/decoding using `prost` (via `hedera-proto-wasm`)
28+
- ✅ Transaction body serialization
29+
- ✅ Compatible with Hedera network format
30+
31+
## ❌ What's Not Available in WASM
32+
33+
These features require networking or execution context and are **native-only**:
34+
35+
-`Client` (network communication)
36+
- ❌ Transaction execution (`.execute()`)
37+
- ❌ Query execution
38+
- ❌ Receipt/Record retrieval
39+
- ❌ Transaction signing **with operator** (`.sign_with_operator()` - requires Client)
40+
- ❌ Transaction freezing **with client** (`.freeze_with(client)` - requires Client)
41+
- ❌ Chunked transaction execution (FileAppend, TopicMessageSubmit)
42+
- ❌ Mirror node queries
43+
- ❌ Flow operations (high-level orchestration)
44+
45+
## 🚀 Use Cases
46+
47+
### Use Case 1: Full Transaction Building & Signing in WASM
48+
49+
**WASM can now handle the complete transaction lifecycle except execution!**
50+
51+
```rust
52+
// In WASM:
53+
let mut tx = TransferTransaction::new();
54+
tx.hbar_transfer(from, -amount)
55+
.hbar_transfer(to, amount)
56+
.transaction_id(TransactionId::generate(from))
57+
.node_account_ids([node_id])
58+
.freeze()?; // ✅ Works in WASM!
59+
60+
let private_key = PrivateKey::from_str("...")?;
61+
tx.sign(private_key); // ✅ Works in WASM!
62+
63+
let signed_bytes = tx.to_bytes()?;
64+
// Send to JavaScript for execution only
65+
```
66+
67+
### Use Case 2: Transaction Building (JavaScript Signs)
68+
69+
Alternatively, **build in WASM and sign in JavaScript**:
70+
71+
```
72+
┌──────────────────────────┐ ┌─────────────────┐
73+
│ Rust/WASM │ │ Hedera Network │
74+
│ │ │ │
75+
│ Build TX → Freeze → Sign │────────▶│ Execute TX │
76+
│ to_bytes() │ bytes │ (via JS client) │
77+
└──────────────────────────┘ └─────────────────┘
78+
```
79+
80+
Or separate signing:
81+
82+
```
83+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
84+
│ Rust/WASM │ │ JavaScript │ │ Hedera Network │
85+
│ │ │ │ │ │
86+
│ Build & Freeze │────────▶│ Sign TX │────────▶│ Execute TX │
87+
│ to_bytes() │ bytes │ (hedera-sdk-js) │ signed │ │
88+
└─────────────────┘ └──────────────────┘ └─────────────────┘
89+
```
90+
91+
### Workflow Options
92+
93+
#### Option A: Full WASM (Build + Sign)
94+
```rust
95+
// WASM does everything except execution
96+
let mut tx = TransferTransaction::new();
97+
tx.hbar_transfer(from, -amount)
98+
.hbar_transfer(to, amount)
99+
.transaction_id(TransactionId::generate(from))
100+
.node_account_ids([node])
101+
.freeze()?;
102+
103+
let key = PrivateKey::from_str(private_key_hex)?;
104+
tx.sign(key);
105+
106+
let signed_bytes = tx.to_bytes()?;
107+
// Send to JavaScript for execution only
108+
```
109+
110+
```javascript
111+
// JavaScript just executes the pre-signed transaction
112+
const signedTxBytes = wasmModule.buildAndSignTransaction(...);
113+
const tx = Transaction.fromBytes(signedTxBytes);
114+
const response = await tx.execute(client);
115+
```
116+
117+
#### Option B: WASM Build, JavaScript Sign
118+
```rust
119+
// WASM builds and freezes
120+
let mut tx = TransferTransaction::new();
121+
tx.hbar_transfer(from, -amount)
122+
.hbar_transfer(to, amount)
123+
.transaction_id(TransactionId::generate(from))
124+
.node_account_ids([node])
125+
.freeze()?;
126+
127+
let bytes = tx.to_bytes()?;
128+
```
129+
130+
```javascript
131+
// JavaScript signs and executes
132+
const txBytes = wasmModule.buildTransaction(...);
133+
const tx = Transaction.fromBytes(txBytes);
134+
const signedTx = await tx.sign(privateKey);
135+
const response = await signedTx.execute(client);
136+
```
137+
138+
## 📦 Building for WASM
139+
140+
### Prerequisites
141+
```bash
142+
rustup target add wasm32-unknown-unknown
143+
```
144+
145+
### Build
146+
```bash
147+
cargo build --target wasm32-unknown-unknown --release
148+
```
149+
150+
### With wasm-bindgen
151+
```bash
152+
cargo install wasm-bindgen-cli
153+
wasm-bindgen target/wasm32-unknown-unknown/release/hedera.wasm \
154+
--out-dir ./pkg \
155+
--target web
156+
```
157+
158+
## 🧪 Testing & Examples
159+
160+
### Run the Demos
161+
162+
#### Basic Transaction Building
163+
```bash
164+
cargo run --example wasm_transaction_demo
165+
```
166+
167+
This demonstrates:
168+
- Building various transaction types
169+
- Serializing to bytes
170+
- Round-trip serialization/deserialization
171+
- Byte inspection
172+
173+
#### Freeze & Sign Demo
174+
```bash
175+
cargo run --example test_wasm_signing
176+
```
177+
178+
This demonstrates:
179+
- ✅ Transaction freezing without client
180+
- ✅ Transaction signing with PrivateKey
181+
- ✅ Serialization of signed transactions
182+
183+
### Expected Output
184+
```
185+
=== Hedera WASM Transaction Building Demo ===
186+
187+
1. Building a Transfer Transaction:
188+
✓ Transaction serialized successfully!
189+
✓ Byte length: 173 bytes
190+
✓ First 20 bytes (hex): 0a aa 01 1a 00 22 50 ...
191+
192+
2. Building a File Create Transaction:
193+
✓ Transaction serialized successfully!
194+
✓ Byte length: 177 bytes
195+
...
196+
197+
✓ WASM-compatible transaction building works!
198+
✓ Transactions can be serialized to bytes
199+
✓ Bytes can be sent to JavaScript for signing and submission
200+
```
201+
202+
## 🔧 Technical Implementation
203+
204+
### Conditional Compilation
205+
The SDK uses `#[cfg(target_arch = "wasm32")]` to conditionally compile:
206+
- Native: Full SDK with networking (tonic, gRPC)
207+
- WASM: Transaction building only (no networking)
208+
209+
### Protobuf Handling
210+
- **Native**: Uses `hedera-proto` with `tonic` for gRPC
211+
- **WASM**: Uses `hedera-proto-wasm` with `prost` only (no tonic dependency)
212+
213+
### Key Architecture Decisions
214+
1. **`TransactionData` trait**: Available for both, defines transaction building
215+
2. **`TransactionExecute` trait**: Native-only, defines networking behavior
216+
3. **`AnyTransaction`**: Available for both, enables type erasure
217+
4. **`ChunkInfo`**: Simplified for WASM (metadata only, no execution)
218+
5. **Error handling**: Full error types available in both targets
219+
220+
## 📝 Known Limitations
221+
222+
1. **Chunking**: FileAppend and TopicMessageSubmit cannot execute multi-chunk transactions in WASM (serialization works for single chunks)
223+
2. **Operator signing**: `.sign_with_operator()` requires Client, not available in WASM (but `.sign()` works!)
224+
3. **Freeze with client**: `.freeze_with(client)` requires Client, not available in WASM (but `.freeze()` works!)
225+
4. **Checksum validation**: Disabled in WASM (returns `Ok(())`)
226+
5. **Prng transactions**: Not available in WASM
227+
6. **Batch transactions**: Not available in WASM
228+
229+
## 🎯 Unlocked Use Cases
230+
231+
With WASM support, you can now:
232+
233+
1. **Complete transaction lifecycle in WASM** (build, freeze, sign, serialize) - only execution needs JavaScript
234+
2. **Type-safe transaction building** in JavaScript applications
235+
3. **Secure private key handling** entirely in WASM (keys never touch JavaScript)
236+
4. **Leverage Rust's performance** for complex transaction construction
237+
5. **Share transaction logic** between Rust backends and JavaScript frontends
238+
6. **Build browser-based** Hedera applications with Rust
239+
7. **Create mobile apps** using React Native + WASM
240+
8. **Offline transaction signing** - prepare and sign transactions without network access
241+
242+
## 🔮 Future Improvements
243+
244+
Potential enhancements:
245+
- [ ] wasm-bindgen bindings for direct JavaScript integration
246+
- [ ] Web Crypto API integration for WASM signing
247+
- [ ] IndexedDB storage for WASM environments
248+
- [ ] More comprehensive WASM examples
249+
- [ ] Performance benchmarks (WASM vs native)
250+
251+
## 📚 Related Resources
252+
253+
- [WebAssembly Official Site](https://webassembly.org/)
254+
- [wasm-bindgen Documentation](https://rustwasm.github.io/wasm-bindgen/)
255+
- [Hedera Documentation](https://docs.hedera.com/)
256+
- [hedera-sdk-js](https://github.com/hashgraph/hedera-sdk-js)
257+
258+
## 🙏 Contributing
259+
260+
Contributions to improve WASM support are welcome! Areas of interest:
261+
- JavaScript integration examples
262+
- Browser-based demos
263+
- Performance optimizations
264+
- Additional transaction types
265+
- Documentation improvements
266+
267+
---
268+
269+
**Note**: WASM support focuses on **transaction building and serialization**. For full Hedera network interaction (signing, execution, queries), use the native Rust SDK or integrate with hedera-sdk-js for the networking layer.
270+

examples/test_wasm_signing.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use hedera::{AccountId, Hbar, PrivateKey, TransactionId, TransferTransaction};
2+
3+
fn main() {
4+
println!("=== Testing WASM Freeze & Sign ===\n");
5+
6+
// Create a transaction
7+
let mut tx = TransferTransaction::new();
8+
tx.hbar_transfer(AccountId::new(0, 0, 1001), Hbar::new(-10))
9+
.hbar_transfer(AccountId::new(0, 0, 1002), Hbar::new(10))
10+
.transaction_id(TransactionId::generate(AccountId::new(0, 0, 1001)))
11+
.node_account_ids([AccountId::new(0, 0, 3)]);
12+
13+
println!("1. Testing freeze():");
14+
match tx.freeze() {
15+
Ok(_) => println!(" ✓ Freeze works!"),
16+
Err(e) => println!(" ✗ Freeze failed: {:?}", e),
17+
}
18+
19+
println!("\n2. Testing sign():");
20+
let private_key = PrivateKey::generate_ed25519();
21+
tx.sign(private_key);
22+
println!(" ✓ Sign works!");
23+
24+
println!("\n3. Testing serialization after signing:");
25+
match tx.to_bytes() {
26+
Ok(bytes) => println!(" ✓ Signed transaction serialized: {} bytes", bytes.len()),
27+
Err(e) => println!(" ✗ Serialization failed: {:?}", e),
28+
}
29+
}

0 commit comments

Comments
 (0)