feat: add native balance in StorageChanges (#292)

* feat: add native balance in StorageChanges

This will be used by the next update of DCI to properly track native balance for all the contract that it's indexing. Also added a performance optimization, we now ignore slot updates if the value after the transaction is the same than before.

* docs: add docs on how to generate test assets

---------

Co-authored-by: zizou <111426680+flopell@users.noreply.github.com>
This commit is contained in:
Zizou
2025-10-06 12:12:37 +02:00
committed by GitHub
parent 128de3037e
commit 568f26116e
12 changed files with 317 additions and 54 deletions

View File

@@ -0,0 +1,95 @@
//! Contains a mock store for internal testing.
//!
//! Might make this public alter to users can test their store handlers.
use std::{cell::RefCell, collections::HashMap, rc::Rc};
use substreams::{
prelude::{BigInt, StoreDelete, StoreGet, StoreNew},
store::StoreAdd,
};
type BigIntStore = HashMap<String, Vec<(u64, BigInt)>>;
#[derive(Debug, Clone)]
pub struct MockStore {
data: Rc<RefCell<BigIntStore>>,
}
impl StoreDelete for MockStore {
fn delete_prefix(&self, _ord: i64, prefix: &String) {
self.data
.borrow_mut()
.retain(|k, _| !k.starts_with(prefix));
}
}
impl StoreNew for MockStore {
fn new() -> Self {
Self { data: Rc::new(RefCell::new(HashMap::new())) }
}
}
impl StoreAdd<BigInt> for MockStore {
fn add<K: AsRef<str>>(&self, ord: u64, key: K, value: BigInt) {
let mut guard = self.data.borrow_mut();
guard
.entry(key.as_ref().to_string())
.and_modify(|v| {
let prev_value = v.last().unwrap().1.clone();
v.push((ord, prev_value + value.clone()));
})
.or_insert(vec![(ord, value)]);
}
fn add_many<K: AsRef<str>>(&self, _ord: u64, _keys: &Vec<K>, _value: BigInt) {
todo!()
}
}
impl StoreGet<BigInt> for MockStore {
fn new(_idx: u32) -> Self {
Self { data: Rc::new(RefCell::new(HashMap::new())) }
}
fn get_at<K: AsRef<str>>(&self, ord: u64, key: K) -> Option<BigInt> {
self.data
.borrow()
.get(&key.as_ref().to_string())
.map(|v| {
v.iter()
.find(|(current_ord, _)| *current_ord == ord)
.unwrap()
.1
.clone()
})
}
fn get_last<K: AsRef<str>>(&self, key: K) -> Option<BigInt> {
self.data
.borrow()
.get(&key.as_ref().to_string())
.map(|v| v.last().unwrap().1.clone())
}
fn get_first<K: AsRef<str>>(&self, key: K) -> Option<BigInt> {
self.data
.borrow()
.get(&key.as_ref().to_string())
.map(|v| v.first().unwrap().1.clone())
}
fn has_at<K: AsRef<str>>(&self, ord: u64, key: K) -> bool {
self.data
.borrow()
.get(&key.as_ref().to_string())
.map(|v| v.iter().any(|(v, _)| *v == ord))
.unwrap_or(false)
}
fn has_last<K: AsRef<str>>(&self, _key: K) -> bool {
todo!()
}
fn has_first<K: AsRef<str>>(&self, _key: K) -> bool {
todo!()
}
}