I did some work on this and I think it's too complicated to do this for Version 4. My findings:
I can move the heavy lifting out of the event listeners and into the "tick" function with the help of an event queue. But I think I need to implement the queue in a more efficient way than shifting and unshifting an array. Maybe a circular buffer would be more performant.
When I have a lot of sand, and then try to draw a wall, gaps appear: