Skip to content

Move transaction indexing logic after deploying an order into gui #1672

@findolor

Description

@findolor

Instead of polling the subgraph on webapp using js, we should do it with a function exported from gui.

gui.awaitDeployment(txhash) could be used to automatically use the correct values to return indexing state.

Here is a simple example using web-sys

use wasm_bindgen::prelude::*;
use web_sys::Window;
use std::rc::Rc;
use std::cell::RefCell;

// A trait for callbacks that can be executed on interval
pub trait IntervalCallback: 'static {
    fn call(&mut self);
}

// Implementation for FnMut closures
impl<F: FnMut() + 'static> IntervalCallback for F {
    fn call(&mut self) {
        self();
    }
}

#[wasm_bindgen]
pub struct IntervalHandle {
    interval_id: i32,
    window: Window,
}

#[wasm_bindgen]
impl IntervalHandle {
    #[wasm_bindgen(constructor)]
    pub fn new(interval_id: i32, window: Window) -> Self {
        Self { interval_id, window }
    }

    #[wasm_bindgen]
    pub fn clear(&self) {
        let _ = self.window.clear_interval_with_handle(self.interval_id);
    }
}

// A struct to hold our callback state
struct CallbackState<T: IntervalCallback> {
    callback: T,
}

// Generic set_interval function with Rust callbacks
pub fn set_interval<T: IntervalCallback>(mut callback: T, delay: i32) -> Result<IntervalHandle, JsValue> {
    let window = web_sys::window().expect("no global window exists");
    
    // Wrap the callback in a new struct to manage its state
    let callback_state = Rc::new(RefCell::new(CallbackState { 
        callback 
    }));
    
    // Clone for closure
    let callback_state_clone = callback_state.clone();
    
    // Create JS closure wrapper
    let closure = Closure::wrap(Box::new(move || {
        // Call the Rust callback
        callback_state_clone.borrow_mut().callback.call();
    }) as Box<dyn FnMut()>);
    
    // Set the interval using the window.setInterval method
    let interval_id = window.set_interval_with_callback_and_timeout_and_arguments_0(
        closure.as_ref().unchecked_ref(),
        delay,
    )?;
    
    // Forget the closure to keep it alive
    // NOTE: This will cause a memory leak if clear() is never called
    closure.forget();
    
    Ok(IntervalHandle::new(interval_id, window))
}

// Example of a counter implementation
pub struct Counter {
    count: i32,
    max: i32,
    handle: Option<IntervalHandle>,
}

impl Counter {
    pub fn new(max: i32) -> Self {
        Self {
            count: 0,
            max,
            handle: None,
        }
    }
    
    pub fn set_handle(&mut self, handle: IntervalHandle) {
        self.handle = Some(handle);
    }
}

impl IntervalCallback for Counter {
    fn call(&mut self) {
        self.count += 1;
        web_sys::console::log_1(&format!("Counter: {}/{}", self.count, self.max).into());
        
        if self.count >= self.max {
            if let Some(handle) = &self.handle {
                handle.clear();
                web_sys::console::log_1(&"Counter interval cleared!".into());
            }
        }
    }
}

// Example function to demonstrate using a custom struct
#[wasm_bindgen]
pub fn start_counter(delay: i32, max_ticks: i32) -> Result<IntervalHandle, JsValue> {
    // Create a counter struct
    let counter = Counter::new(max_ticks);
    
    // Set up interval with the counter as callback
    let handle = set_interval(counter, delay)?;
    
    Ok(handle)
}

// Example with a simple closure
#[wasm_bindgen]
pub fn simple_interval(delay: i32) -> Result<IntervalHandle, JsValue> {
    // Create a counter in a closure
    let counter = Rc::new(RefCell::new(0));
    let counter_clone = counter.clone();
    
    let closure = move || {
        let mut count = counter_clone.borrow_mut();
        *count += 1;
        web_sys::console::log_1(&format!("Tick: {}", *count).into());
    };
    
    set_interval(closure, delay)
}

// Self-clearing interval example
#[wasm_bindgen]
pub fn self_clearing_interval(delay: i32, max_ticks: i32) -> Result<IntervalHandle, JsValue> {
    // Create a counter and handle reference
    let counter = Rc::new(RefCell::new(0));
    let handle_ref = Rc::new(RefCell::new(None));
    
    // Clone for closure
    let counter_clone = counter.clone();
    let handle_ref_clone = handle_ref.clone();
    
    let closure = move || {
        let mut count = counter_clone.borrow_mut();
        *count += 1;
        web_sys::console::log_1(&format!("Tick: {}/{}", *count, max_ticks).into());
        
        if *count >= max_ticks {
            if let Some(handle) = &*handle_ref_clone.borrow() {
                handle.clear();
                web_sys::console::log_1(&"Interval cleared!".into());
            }
        }
    };
    
    // Set interval with our closure
    let handle = set_interval(closure, delay)?;
    
    // Store handle for later use in the closure
    *handle_ref.borrow_mut() = Some(IntervalHandle::new(handle.interval_id, handle.window));
    
    Ok(handle)
}

Metadata

Metadata

Assignees

Labels

rustRelated to rust crateswebapp

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions